From e7c3abe3622bc341fe35c5a662bc7173004585ac Mon Sep 17 00:00:00 2001 From: pasta Date: Mon, 20 Feb 2023 09:28:41 -0600 Subject: [PATCH 01/63] chore: update version to v19.0.0-rc.1 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 943ce8e8ab..cc2df55112 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 19) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 0) +define(_CLIENT_VERSION_RC, 1) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2023) define(_COPYRIGHT_HOLDERS,[The %s developers]) From 38c481ce25e17b846b4ded4ef80a1ee5be87ddcc Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Tue, 21 Feb 2023 17:04:33 +0200 Subject: [PATCH 02/63] chore: Added missing protx rpc in help (#5216) ## Issue being fixed or feature implemented ## What was done? `update_registrar_legacy` was missing from the protx help output. ## How Has This Been Tested? ## Breaking Changes ## 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 - [x] I have made corresponding changes to the documentation **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/rpc/evo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rpc/evo.cpp b/src/rpc/evo.cpp index a93d08a9e6..b334be7f49 100644 --- a/src/rpc/evo.cpp +++ b/src/rpc/evo.cpp @@ -1478,6 +1478,7 @@ static UniValue protx_diff(const JSONRPCRequest& request) " update_service - Create and send ProUpServTx to network\n" " update_service_hpmn - Create and send ProUpServTx to network for a HPMN\n" " update_registrar - Create and send ProUpRegTx to network\n" + " update_registrar_legacy - Create ProUpRegTx by parsing BLS using the legacy scheme, then send it to network\n" " revoke - Create and send ProUpRevTx to network\n" #endif " diff - Calculate a diff and a proof between two masternode lists\n", From 3a24170ac3f10184884a2ae56d3811bb9f93d5a7 Mon Sep 17 00:00:00 2001 From: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> Date: Wed, 22 Feb 2023 11:08:57 -0600 Subject: [PATCH 03/63] chore: set the nStartTime for v19 deployment Fed 22 and March 31st respectively (#5218) ## Issue being fixed or feature implemented ## What was done? ## How Has This Been Tested? ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/chainparams.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 73c450b2d6..9e8bc8cbd4 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -248,8 +248,8 @@ public: // Deployment of Deployment of Basic BLS, AssetLocks, EHF consensus.vDeployments[Consensus::DEPLOYMENT_V19].bit = 8; - consensus.vDeployments[Consensus::DEPLOYMENT_V19].nStartTime = 19999999999; // TODO: To be determined later - consensus.vDeployments[Consensus::DEPLOYMENT_V19].nTimeout = 999999999999ULL; + consensus.vDeployments[Consensus::DEPLOYMENT_V19].nStartTime = 1680220800; // Fri, Mar 31, 2023 0:00:00 + consensus.vDeployments[Consensus::DEPLOYMENT_V19].nTimeout = 1711843200; // Sun, Mar 31, 2024 00:00:00 consensus.vDeployments[Consensus::DEPLOYMENT_V19].nWindowSize = 4032; consensus.vDeployments[Consensus::DEPLOYMENT_V19].nThresholdStart = 3226; // 80% of 4032 consensus.vDeployments[Consensus::DEPLOYMENT_V19].nThresholdMin = 2420; // 60% of 4032 @@ -486,7 +486,7 @@ public: // Deployment of Deployment of Basic BLS, AssetLocks, EHF consensus.vDeployments[Consensus::DEPLOYMENT_V19].bit = 8; - consensus.vDeployments[Consensus::DEPLOYMENT_V19].nStartTime = 19999999999; // TODO: To be determined later + consensus.vDeployments[Consensus::DEPLOYMENT_V19].nStartTime = 1677024000; // Wed, Feb 22, 2023 0:00:00 consensus.vDeployments[Consensus::DEPLOYMENT_V19].nTimeout = 999999999999ULL; consensus.vDeployments[Consensus::DEPLOYMENT_V19].nWindowSize = 100; consensus.vDeployments[Consensus::DEPLOYMENT_V19].nThresholdStart = 80; // 80% of 100 From 01ebd60187c2c6ee9ef40bbadd946f8005ea60de Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Wed, 22 Feb 2023 19:10:28 +0200 Subject: [PATCH 04/63] fix(rpc): don't parse platformHTTPPort platformP2PPort as strings (#5217) ## Issue being fixed or feature implemented In `protx register_hpmn`, `protx register_fund_hpmn`, `protx register_prepare_hpmn` and `protx update_service_hpmn` the fields `platformHTTPPort` and `platformP2PPort` were parsed as strings instead of integers. ## What was done? ## How Has This Been Tested? ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/rpc/evo.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rpc/evo.cpp b/src/rpc/evo.cpp index b334be7f49..9735000787 100644 --- a/src/rpc/evo.cpp +++ b/src/rpc/evo.cpp @@ -665,13 +665,13 @@ static UniValue protx_register_common_wrapper(const JSONRPCRequest& request, } ptx.platformNodeID.SetHex(request.params[paramIdx + 6].get_str()); - int32_t requestedPlatformP2PPort = ParseInt32V(request.params[paramIdx + 7].get_str(), "platformP2PPort"); + int32_t requestedPlatformP2PPort = ParseInt32V(request.params[paramIdx + 7], "platformP2PPort"); if (!ValidatePlatformPort(requestedPlatformP2PPort)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "platformP2PPort must be a valid port [1-65535]"); } ptx.platformP2PPort = static_cast(requestedPlatformP2PPort); - int32_t requestedPlatformHTTPPort = ParseInt32V(request.params[paramIdx + 8].get_str(), "platformHTTPPort"); + int32_t requestedPlatformHTTPPort = ParseInt32V(request.params[paramIdx + 8], "platformHTTPPort"); if (!ValidatePlatformPort(requestedPlatformHTTPPort)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "platformHTTPPort must be a valid port [1-65535]"); } @@ -899,13 +899,13 @@ static UniValue protx_update_service_common_wrapper(const JSONRPCRequest& reques } ptx.platformNodeID.SetHex(request.params[paramIdx].get_str()); - int32_t requestedPlatformP2PPort = ParseInt32V(request.params[paramIdx + 1].get_str(), "platformP2PPort"); + int32_t requestedPlatformP2PPort = ParseInt32V(request.params[paramIdx + 1], "platformP2PPort"); if (!ValidatePlatformPort(requestedPlatformP2PPort)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "platformP2PPort must be a valid port [1-65535]"); } ptx.platformP2PPort = static_cast(requestedPlatformP2PPort); - int32_t requestedPlatformHTTPPort = ParseInt32V(request.params[paramIdx + 2].get_str(), "platformHTTPPort"); + int32_t requestedPlatformHTTPPort = ParseInt32V(request.params[paramIdx + 2], "platformHTTPPort"); if (!ValidatePlatformPort(requestedPlatformHTTPPort)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "platformHTTPPort must be a valid port [1-65535]"); } From 593034b6f2bac38ee0a77091df17c87d22d17db2 Mon Sep 17 00:00:00 2001 From: pasta Date: Wed, 22 Feb 2023 11:15:16 -0600 Subject: [PATCH 05/63] chore: bump version to rc.2 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index cc2df55112..d4230c862d 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 19) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 1) +define(_CLIENT_VERSION_RC, 2) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2023) define(_COPYRIGHT_HOLDERS,[The %s developers]) From 368e48cb16476bf1b5e29ed166aed6e53b86f963 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Tue, 28 Feb 2023 17:55:37 +0200 Subject: [PATCH 06/63] bump rc3 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d4230c862d..e605170270 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 19) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 2) +define(_CLIENT_VERSION_RC, 3) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2023) define(_COPYRIGHT_HOLDERS,[The %s developers]) From c83d4881df26bb303882ecd453dacbcf2212c695 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Tue, 28 Feb 2023 12:11:07 +0700 Subject: [PATCH 07/63] chrore: bump version in gitian to 19 (#5220) Name of some files in gitian's build contains "18" instead 19. ## Issue being fixed or feature implemented ## What was done? Version bumped in gitian's related configs ## How Has This Been Tested? Will be tested with next RC of v19 ## Breaking Changes No breaking changes ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have made corresponding changes to the documentation @PastaPastaPasta may you update release TODO checklist, please? - [x] I have assigned this pull request to a milestone --- contrib/gitian-descriptors/gitian-linux.yml | 2 +- contrib/gitian-descriptors/gitian-osx.yml | 2 +- contrib/gitian-descriptors/gitian-win.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 4a14a0ce44..809e0d5870 100755 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "dash-linux-18" +name: "dash-linux-19" enable_cache: true distro: "ubuntu" suites: diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 6c8dfac38c..0a2102887f 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -1,5 +1,5 @@ --- -name: "dash-osx-18" +name: "dash-osx-19" enable_cache: true distro: "ubuntu" suites: diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 5b1b096d29..cbf76eb509 100755 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -1,5 +1,5 @@ --- -name: "dash-win-18" +name: "dash-win-19" enable_cache: true distro: "ubuntu" suites: From db978cef54cf15fb38626281114582e3e37af2ad Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Mon, 27 Feb 2023 20:50:02 +0300 Subject: [PATCH 08/63] fix(qt): Overview page should always be accessible (#5221) ## Issue being fixed or feature implemented Overview page shows either wallet info or "Create wallet" button. Unlike in bitcoin we can switch to other pages even when no wallets are enabled (because we have Masternodes and Governance tabs) but then there is no way to return back to Overview page. ## What was done? Keep Overview tab always enabled. Make a no-wallet groupbox a member of `WalletFrame` and add logic to switch to it when needed. ## How Has This Been Tested? `./src/qt/dash-qt --regtest --nowallet` ## 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 - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation **For repository code-owners and collaborators only** - [ ] I have assigned this pull request to a milestone PS. kudos to @thephez for reporting :) --- src/qt/bitcoingui.cpp | 2 +- src/qt/walletframe.cpp | 9 +++++++-- src/qt/walletframe.h | 2 ++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 32ec843b02..9851801a9f 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -939,7 +939,7 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled) { #ifdef ENABLE_WALLET if (walletFrame != nullptr) { - overviewButton->setEnabled(enabled); + // NOTE: overviewButton is always enabled sendCoinsButton->setEnabled(enabled); coinJoinCoinsButton->setEnabled(enabled && clientModel->coinJoinOptions().isEnabled()); receiveCoinsButton->setEnabled(enabled); diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 5a478109d4..5864820499 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -14,7 +14,6 @@ #include -#include #include #include #include @@ -32,7 +31,7 @@ WalletFrame::WalletFrame(BitcoinGUI* _gui) : walletFrameLayout->addWidget(walletStack); // hbox for no wallet - QGroupBox* no_wallet_group = new QGroupBox(walletStack); + no_wallet_group = new QGroupBox(walletStack); QVBoxLayout* no_wallet_layout = new QVBoxLayout(no_wallet_group); QLabel *noWallet = new QLabel(tr("No wallet has been loaded.\nGo to File > Open Wallet to load a wallet.\n- OR -")); @@ -172,6 +171,12 @@ void WalletFrame::gotoGovernancePage() void WalletFrame::gotoOverviewPage() { QMap::const_iterator i; + + if (mapWalletViews.empty()) { + walletStack->setCurrentWidget(no_wallet_group); + return; + } + for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) i.value()->gotoOverviewPage(); } diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 5fbd5ca4ad..d66225c5cf 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -6,6 +6,7 @@ #define BITCOIN_QT_WALLETFRAME_H #include +#include #include class BitcoinGUI; @@ -55,6 +56,7 @@ private: BitcoinGUI *gui; ClientModel *clientModel; QMap mapWalletViews; + QGroupBox* no_wallet_group; MasternodeList* masternodeListPage; GovernanceList* governanceListPage; From 088c8a55d2ac7d7e75223a05ed6f25ea994ab906 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Tue, 28 Feb 2023 04:13:01 +0700 Subject: [PATCH 09/63] fix: making builds of guix to produce same output whatever git config (#5222) Builds are different, because git command output are different: ## Issue being fixed or feature implemented in pr #5194 different OS produced different hashes of binary. That's due to different behaviour of this command: ```sh $ git rev-parse --short HEAD b3f242da14 - on my localhost Kubuntu 22.10 b3f242da1 - inside pastapastapasta's docker ``` ## What was done? This fix forces to git print always 12 character ## How Has This Been Tested? Run in different environment ## Breaking Changes No breaking changes ## Checklist: - [x] I have performed a self-review of my own code - [x] I have assigned this pull request to a milestone --- share/genbuild.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/genbuild.sh b/share/genbuild.sh index 804d56effd..7e34390d78 100755 --- a/share/genbuild.sh +++ b/share/genbuild.sh @@ -31,7 +31,7 @@ if [ "${BITCOIN_GENBUILD_NO_GIT}" != "1" ] && [ -e "$(command -v git)" ] && [ "$ fi # otherwise generate suffix from git, i.e. string like "59887e8-dirty" - GIT_COMMIT=$(git rev-parse --short HEAD) + GIT_COMMIT=$(git rev-parse --short=12 HEAD) git diff-index --quiet HEAD -- || GIT_COMMIT="$GIT_COMMIT-dirty" fi From 5826464fc96b7deca1af70ec729be84c3f19be6f Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Tue, 28 Feb 2023 17:59:57 +0200 Subject: [PATCH 10/63] chore: Bump MIN_MASTERNODE_PROTO_VERSION for v19 (#5223) ## Issue being fixed or feature implemented ## What was done? `MIN_MASTERNODE_PROTO_VERSION` was bumped to match latest `PROTOCOL_VERSION`. ## How Has This Been Tested? ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 456b44d784..a2114db494 100644 --- a/src/version.h +++ b/src/version.h @@ -20,7 +20,7 @@ static const int INIT_PROTO_VERSION = 209; static const int MIN_PEER_PROTO_VERSION = 70215; //! minimum proto version of masternode to accept in DKGs -static const int MIN_MASTERNODE_PROTO_VERSION = 70221; +static const int MIN_MASTERNODE_PROTO_VERSION = 70227; //! nTime field added to CAddress, starting with this version; //! if possible, avoid requesting addresses nodes older than this From eae0cbacb72c3db369069a22f345bb4c89d945d2 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Wed, 1 Mar 2023 19:42:33 +0200 Subject: [PATCH 11/63] feat(llmq): llmq_25_67 for Platform (Testnet only) (#5225) ## Issue being fixed or feature implemented ## What was done? - Added new LLMQ type `llmq_25_67` - The above LLMQ is added only for Testnet and it is activated with v19 fork. ## How Has This Been Tested? ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --------- Co-authored-by: pasta --- doc/release-notes-5225.md | 10 ++++++++++ src/chainparams.cpp | 3 ++- src/llmq/params.h | 30 +++++++++++++++++++++++++++++- src/llmq/utils.cpp | 7 +++++++ 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 doc/release-notes-5225.md diff --git a/doc/release-notes-5225.md b/doc/release-notes-5225.md new file mode 100644 index 0000000000..9a85026015 --- /dev/null +++ b/doc/release-notes-5225.md @@ -0,0 +1,10 @@ +Testnet Breaking Changes +------------------------ + +A new testnet only LLMQ has been added. This LLMQ is of the type LLMQ_25_67; this LLMQ is only active on testnet. +This LLMQ will not remove the LLMQ_100_67 from testnet; however that quorum (likely) will not form and will perform no role. +See the [diff](https://github.com/dashpay/dash/pull/5225/files#diff-e70a38a3e8c2a63ca0494627301a5c7042141ad301193f78338d97cb1b300ff9R451-R469) for specific parameters of the LLMQ. + +This LLMQ will become active at the height of 847000. **This will be a breaking change and a hard fork for testnet** +This LLMQ is not activated with the v19 hardfork; as such testnet will experience two hardforks. One at height 847000, +and the other to be determined by the BIP9 hard fork process. diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 9e8bc8cbd4..c69a21062d 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -542,10 +542,11 @@ public: AddLLMQ(Consensus::LLMQType::LLMQ_400_60); AddLLMQ(Consensus::LLMQType::LLMQ_400_85); AddLLMQ(Consensus::LLMQType::LLMQ_100_67); + AddLLMQ(Consensus::LLMQType::LLMQ_25_67); consensus.llmqTypeChainLocks = Consensus::LLMQType::LLMQ_50_60; consensus.llmqTypeInstantSend = Consensus::LLMQType::LLMQ_50_60; consensus.llmqTypeDIP0024InstantSend = Consensus::LLMQType::LLMQ_60_75; - consensus.llmqTypePlatform = Consensus::LLMQType::LLMQ_100_67; + consensus.llmqTypePlatform = Consensus::LLMQType::LLMQ_25_67; consensus.llmqTypeMnhf = Consensus::LLMQType::LLMQ_50_60; fDefaultConsistencyChecks = false; diff --git a/src/llmq/params.h b/src/llmq/params.h index e9aed66daf..248c355310 100644 --- a/src/llmq/params.h +++ b/src/llmq/params.h @@ -19,6 +19,7 @@ enum class LLMQType : uint8_t { LLMQ_400_85 = 3, // 400 members, 340 (85%) threshold, one every 24 hours LLMQ_100_67 = 4, // 100 members, 67 (67%) threshold, one per hour LLMQ_60_75 = 5, // 60 members, 45 (75%) threshold, one every 12 hours + LLMQ_25_67 = 6, // 25 members, 67 (67%) threshold, one per hour // for testing only LLMQ_TEST = 100, // 3 members, 2 (66%) threshold, one per hour. Params might differ when -llmqtestparams is used @@ -108,7 +109,7 @@ struct LLMQParams { }; -static constexpr std::array available_llmqs = { +static constexpr std::array available_llmqs = { /** * llmq_test @@ -440,6 +441,33 @@ static constexpr std::array available_llmqs = { .recoveryMembers = 50, }, + /** + * llmq_25_67 + * This quorum is deployed on Testnet and requires + * 25 participants + * + * Used by Dash Platform + */ + LLMQParams{ + .type = LLMQType::LLMQ_25_67, + .name = "llmq_25_67", + .useRotation = false, + .size = 25, + .minSize = 22, + .threshold = 17, + + .dkgInterval = 24, // one DKG per hour + .dkgPhaseBlocks = 2, + .dkgMiningWindowStart = 10, // dkgPhaseBlocks * 5 = after finalization + .dkgMiningWindowEnd = 18, + .dkgBadVotesThreshold = 22, + + .signingActiveQuorumCount = 24, // a full day worth of LLMQs + + .keepOldConnections = 25, + .recoveryMembers = 12, + }, + }; // available_llmqs } // namespace Consensus diff --git a/src/llmq/utils.cpp b/src/llmq/utils.cpp index 552d2abb70..5e5c6417c2 100644 --- a/src/llmq/utils.cpp +++ b/src/llmq/utils.cpp @@ -24,6 +24,8 @@ #include +static constexpr int TESTNET_LLMQ_25_67_ACTIVATION_HEIGHT = 847000; + namespace llmq { @@ -954,6 +956,11 @@ bool IsQuorumTypeEnabledInternal(Consensus::LLMQType llmqType, const CQuorumMana } break; } + case Consensus::LLMQType::LLMQ_25_67: + if (pindex->nHeight < TESTNET_LLMQ_25_67_ACTIVATION_HEIGHT) { + return false; + } + break; default: throw std::runtime_error(strprintf("%s: Unknown LLMQ type %d", __func__, ToUnderlying(llmqType))); } From 0bcf96311ffcced50ded37dc9a198e7b00c881ba Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Wed, 1 Mar 2023 21:07:54 +0200 Subject: [PATCH 12/63] feat(llmq): llmq_test_dip0024 adjustments (#5229) ## Issue being fixed or feature implemented ## What was done? ## How Has This Been Tested? ## Breaking Changes After the DIP24 fork, instant locks will still be served by `llmq_test_instantsend`, since no `llmq_test_dip0024` will be formed with less than 4 nodes. ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/llmq/params.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llmq/params.h b/src/llmq/params.h index 248c355310..2f0ac1f8eb 100644 --- a/src/llmq/params.h +++ b/src/llmq/params.h @@ -196,7 +196,7 @@ static constexpr std::array available_llmqs = { .name = "llmq_test_dip0024", .useRotation = true, .size = 4, - .minSize = 3, + .minSize = 4, .threshold = 2, .dkgInterval = 24, // DKG cycle From f63676ba5f8347a04514f7c96bd5274160138720 Mon Sep 17 00:00:00 2001 From: pasta Date: Wed, 1 Mar 2023 11:48:25 -0600 Subject: [PATCH 13/63] chore: bump version to rc.4 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e605170270..b8e46e702c 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 19) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 3) +define(_CLIENT_VERSION_RC, 4) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2023) define(_COPYRIGHT_HOLDERS,[The %s developers]) From 45da082dda0625dc8f8777c0d6690939d5eb5244 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 1 Mar 2023 22:51:36 +0300 Subject: [PATCH 14/63] fix(doc): fix `release-notes-5225.md` (#5230) ## Issue being fixed or feature implemented make linter happy, fix failures like https://gitlab.com/dashpay/dash/-/jobs/3858504407 ## What was done? drop trailing whitespace ## How Has This Been Tested? `COMMIT_RANGE=1a810ca07d..HEAD ./test/lint/lint-whitespace.sh ` fails on develop, passes on this branch ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- doc/release-notes-5225.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes-5225.md b/doc/release-notes-5225.md index 9a85026015..e6cdc29679 100644 --- a/doc/release-notes-5225.md +++ b/doc/release-notes-5225.md @@ -1,7 +1,7 @@ Testnet Breaking Changes ------------------------ -A new testnet only LLMQ has been added. This LLMQ is of the type LLMQ_25_67; this LLMQ is only active on testnet. +A new testnet only LLMQ has been added. This LLMQ is of the type LLMQ_25_67; this LLMQ is only active on testnet. This LLMQ will not remove the LLMQ_100_67 from testnet; however that quorum (likely) will not form and will perform no role. See the [diff](https://github.com/dashpay/dash/pull/5225/files#diff-e70a38a3e8c2a63ca0494627301a5c7042141ad301193f78338d97cb1b300ff9R451-R469) for specific parameters of the LLMQ. From 66b0cf74cedd733c5d86afe420ed888d65ce7b57 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 2 Mar 2023 19:55:44 +0300 Subject: [PATCH 15/63] fix: postpone v19 hf start time on testnet (#5231) ## Issue being fixed or feature implemented Block 847000 hf should happen somewhere around March 4th. We need mining nodes to be upgraded to follow that chain and mine correct blocks. However we don't want v19 to be activated shortly after (~300 blocks), we want to give it a little bit of time to let (new) platform quorums form and make sure everything is ok. With this patch we should have ~2 days (instead of half of a day). ## What was done? bumped v19 activation start time to March 6th ## How Has This Been Tested? n/a ## Breaking Changes yes :) ## 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 **For repository code-owners and collaborators only** - [ ] I have assigned this pull request to a milestone --- src/chainparams.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index c69a21062d..0945f964c4 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -486,7 +486,7 @@ public: // Deployment of Deployment of Basic BLS, AssetLocks, EHF consensus.vDeployments[Consensus::DEPLOYMENT_V19].bit = 8; - consensus.vDeployments[Consensus::DEPLOYMENT_V19].nStartTime = 1677024000; // Wed, Feb 22, 2023 0:00:00 + consensus.vDeployments[Consensus::DEPLOYMENT_V19].nStartTime = 1678060800; // Tue, March 06, 2023 0:00:00 consensus.vDeployments[Consensus::DEPLOYMENT_V19].nTimeout = 999999999999ULL; consensus.vDeployments[Consensus::DEPLOYMENT_V19].nWindowSize = 100; consensus.vDeployments[Consensus::DEPLOYMENT_V19].nThresholdStart = 80; // 80% of 100 From 103523d221da128ee73121f46e524584878a03bc Mon Sep 17 00:00:00 2001 From: pasta Date: Thu, 2 Mar 2023 10:57:39 -0600 Subject: [PATCH 16/63] chore: bump to rc.5 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index b8e46e702c..930ef433b9 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 19) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 4) +define(_CLIENT_VERSION_RC, 5) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2023) define(_COPYRIGHT_HOLDERS,[The %s developers]) From 14c63af1efdf777dccdf38d2c34f3146c6dfd48e Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Sat, 11 Mar 2023 19:46:49 +0200 Subject: [PATCH 17/63] docs(rpc): correct help for protx legacy versions (#5234) ## Issue being fixed or feature implemented Help text for protx legacy versions were adjusted. ## What was done? ## How Has This Been Tested? ## Breaking Changes ## 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 - [x] I have made corresponding changes to the documentation **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --------- Co-authored-by: thephez --- src/rpc/evo.cpp | 67 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/src/rpc/evo.cpp b/src/rpc/evo.cpp index 9735000787..02122abb34 100644 --- a/src/rpc/evo.cpp +++ b/src/rpc/evo.cpp @@ -89,12 +89,23 @@ static RPCArg GetRpcArg(const std::string& strParamName) "The operator BLS public key. The BLS private key does not have to be known.\n" "It has to match the BLS private key which is later used when operating the masternode."} }, + {"operatorPubKey_register_legacy", + {"operatorPubKey_register", RPCArg::Type::STR, RPCArg::Optional::NO, + "The operator BLS public key in legacy scheme. The BLS private key does not have to be known.\n" + "It has to match the BLS private key which is later used when operating the masternode.\n"} + }, {"operatorPubKey_update", {"operatorPubKey_update", RPCArg::Type::STR, RPCArg::Optional::NO, "The operator BLS public key. The BLS private key does not have to be known.\n" "It has to match the BLS private key which is later used when operating the masternode.\n" "If set to an empty string, the currently active operator BLS public key is reused."} }, + {"operatorPubKey_update_legacy", + {"operatorPubKey_update", RPCArg::Type::STR, RPCArg::Optional::NO, + "The operator BLS public key in legacy scheme. The BLS private key does not have to be known.\n" + "It has to match the BLS private key which is later used when operating the masternode.\n" + "If set to an empty string, the currently active operator BLS public key is reused."} + }, {"operatorReward", {"operatorReward", RPCArg::Type::STR, RPCArg::Optional::NO, "The fraction in %% to share with the operator. The value must be\n" @@ -339,9 +350,13 @@ static std::string SignAndSendSpecialTx(const JSONRPCRequest& request, const CMu return sendrawtransaction(sendRequest).get_str(); } -static void protx_register_fund_help(const JSONRPCRequest& request) +static void protx_register_fund_help(const JSONRPCRequest& request, bool legacy) { - RPCHelpMan{"protx register_fund", + std::string rpc_name = legacy ? "register_fund_legacy" : "register_fund"; + std::string rpc_full_name = std::string("protx ").append(rpc_name); + std::string pubkey_operator = legacy ? "\"0532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\"" : "\"8532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\""; + std::string rpc_example = rpc_name.append(" \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\" \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" ").append(pubkey_operator).append(" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\""); + RPCHelpMan{rpc_full_name, "\nCreates, funds and sends a ProTx to the network. The resulting transaction will move 1000 Dash\n" "to the address specified by collateralAddress and will then function as the collateral of your\n" "masternode.\n" @@ -352,7 +367,7 @@ static void protx_register_fund_help(const JSONRPCRequest& request) GetRpcArg("collateralAddress"), GetRpcArg("ipAndPort"), GetRpcArg("ownerAddress"), - GetRpcArg("operatorPubKey_register"), + legacy ? GetRpcArg("operatorPubKey_register_legacy") : GetRpcArg("operatorPubKey_register"), GetRpcArg("votingAddress_register"), GetRpcArg("operatorReward"), GetRpcArg("payoutAddress_register"), @@ -366,14 +381,18 @@ static void protx_register_fund_help(const JSONRPCRequest& request) RPCResult::Type::STR_HEX, "hex", "The serialized signed ProTx in hex format"}, }, RPCExamples{ - HelpExampleCli("protx", "register_fund \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\" \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\"") + HelpExampleCli("protx", rpc_example) }, }.Check(request); } -static void protx_register_help(const JSONRPCRequest& request) +static void protx_register_help(const JSONRPCRequest& request, bool legacy) { - RPCHelpMan{"protx register", + std::string rpc_name = legacy ? "register_legacy" : "register"; + std::string rpc_full_name = std::string("protx ").append(rpc_name); + std::string pubkey_operator = legacy ? "\"0532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\"" : "\"8532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\""; + std::string rpc_example = rpc_name.append(" \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" ").append(pubkey_operator).append(" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\""); + RPCHelpMan{rpc_full_name, "\nSame as \"protx register_fund\", but with an externally referenced collateral.\n" "The collateral is specified through \"collateralHash\" and \"collateralIndex\" and must be an unspent\n" "transaction output spendable by this wallet. It must also not be used by any other masternode.\n" @@ -383,7 +402,7 @@ static void protx_register_help(const JSONRPCRequest& request) GetRpcArg("collateralIndex"), GetRpcArg("ipAndPort"), GetRpcArg("ownerAddress"), - GetRpcArg("operatorPubKey_register"), + legacy ? GetRpcArg("operatorPubKey_register_legacy") : GetRpcArg("operatorPubKey_register"), GetRpcArg("votingAddress_register"), GetRpcArg("operatorReward"), GetRpcArg("payoutAddress_register"), @@ -397,14 +416,18 @@ static void protx_register_help(const JSONRPCRequest& request) RPCResult::Type::STR_HEX, "hex", "The serialized signed ProTx in hex format"}, }, RPCExamples{ - HelpExampleCli("protx", "register \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\"") + HelpExampleCli("protx", rpc_example) }, }.Check(request); } -static void protx_register_prepare_help(const JSONRPCRequest& request) +static void protx_register_prepare_help(const JSONRPCRequest& request, bool legacy) { - RPCHelpMan{"protx register_prepare", + std::string rpc_name = legacy ? "register_prepare_legacy" : "register_prepare"; + std::string rpc_full_name = std::string("protx ").append(rpc_name); + std::string pubkey_operator = legacy ? "\"0532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\"" : "\"8532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\""; + std::string rpc_example = rpc_name.append(" \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" ").append(pubkey_operator).append(" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\""); + RPCHelpMan{rpc_full_name, "\nCreates an unsigned ProTx and a message that must be signed externally\n" "with the private key that corresponds to collateralAddress to prove collateral ownership.\n" "The prepared transaction will also contain inputs and outputs to cover fees.\n", @@ -413,7 +436,7 @@ static void protx_register_prepare_help(const JSONRPCRequest& request) GetRpcArg("collateralIndex"), GetRpcArg("ipAndPort"), GetRpcArg("ownerAddress"), - GetRpcArg("operatorPubKey_register"), + legacy ? GetRpcArg("operatorPubKey_register_legacy") : GetRpcArg("operatorPubKey_register"), GetRpcArg("votingAddress_register"), GetRpcArg("operatorReward"), GetRpcArg("payoutAddress_register"), @@ -427,7 +450,7 @@ static void protx_register_prepare_help(const JSONRPCRequest& request) {RPCResult::Type::STR_HEX, "signMessage", "The string message that needs to be signed with the collateral key"}, }}, RPCExamples{ - HelpExampleCli("protx", "register_prepare \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\"") + HelpExampleCli("protx", rpc_example) }, }.Check(request); } @@ -570,11 +593,11 @@ static UniValue protx_register_common_wrapper(const JSONRPCRequest& request, } } else { if (isFundRegister && (request.fHelp || (request.params.size() < 7 || request.params.size() > 9))) { - protx_register_fund_help(request); + protx_register_fund_help(request, specific_legacy_bls_scheme); } else if (isExternalRegister && (request.fHelp || (request.params.size() < 8 || request.params.size() > 10))) { - protx_register_help(request); + protx_register_help(request, specific_legacy_bls_scheme); } else if (isPrepareRegister && (request.fHelp || (request.params.size() != 8 && request.params.size() != 9))) { - protx_register_prepare_help(request); + protx_register_prepare_help(request, specific_legacy_bls_scheme); } } @@ -970,16 +993,20 @@ static UniValue protx_update_service_common_wrapper(const JSONRPCRequest& reques return SignAndSendSpecialTx(request, tx); } -static void protx_update_registrar_help(const JSONRPCRequest& request) +static void protx_update_registrar_help(const JSONRPCRequest& request, bool legacy) { - RPCHelpMan{"protx update_registrar", + std::string rpc_name = legacy ? "update_registrar_legacy" : "update_registrar"; + std::string rpc_full_name = std::string("protx ").append(rpc_name); + std::string pubkey_operator = legacy ? "\"0532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\"" : "\"8532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\""; + std::string rpc_example = rpc_name.append(" \"0123456701234567012345670123456701234567012345670123456701234567\" ").append(pubkey_operator).append(" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\""); + RPCHelpMan{rpc_full_name, "\nCreates and sends a ProUpRegTx to the network. This will update the operator key, voting key and payout\n" "address of the masternode specified by \"proTxHash\".\n" "The owner key of the masternode must be known to your wallet.\n" + HELP_REQUIRING_PASSPHRASE, { GetRpcArg("proTxHash"), - GetRpcArg("operatorPubKey_update"), + legacy ? GetRpcArg("operatorPubKey_update_legacy") : GetRpcArg("operatorPubKey_update"), GetRpcArg("votingAddress_update"), GetRpcArg("payoutAddress_update"), GetRpcArg("feeSourceAddress"), @@ -988,14 +1015,14 @@ static void protx_update_registrar_help(const JSONRPCRequest& request) RPCResult::Type::STR_HEX, "txid", "The transaction id" }, RPCExamples{ - HelpExampleCli("protx", "update_registrar \"0123456701234567012345670123456701234567012345670123456701234567\" \"982eb34b7c7f614f29e5c665bc3605f1beeef85e3395ca12d3be49d2868ecfea5566f11cedfad30c51b2403f2ad95b67\" \"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\"") + HelpExampleCli("protx", rpc_example) }, }.Check(request); } static UniValue protx_update_registrar_wrapper(const JSONRPCRequest& request, const bool specific_legacy_bls_scheme) { - protx_update_registrar_help(request); + protx_update_registrar_help(request, specific_legacy_bls_scheme); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; From ce524c4a5404cb5f93a4b72ab4e3428a4b12c76f Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Sat, 11 Mar 2023 19:42:27 +0200 Subject: [PATCH 18/63] fix: mnUniquePropertyMap repopulate for v19 (#5239) ## Issue being fixed or feature implemented `CDeterministicMNList` stores internally a map containing the hashes of all properties that needed to be unique. `pubKeyOperator` don't differ between the two schemes (legacy and basic(v19)) but their serialisation do: hence their hash. Because this internal map stores only hashes, then we need to re-calculate hashes and repopulate. So when we tried to revoke a masternode after the fork, the `ProUpRevTx` couldn't be mined because the hash of the `pubKeyOperator` differed. ## What was done? When retrieving a `CDeterministicMNList` for a given block, if v19 is active for that block, then we repopulate the internal map. ## How Has This Been Tested? Without this fix, `feature_dip3_v19.py` is failing with `failed-calc-cb-mnmerkleroot` (Error encountered on Testnet) ## Breaking Changes ## 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 - [ ] I have made corresponding changes to the documentation **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --------- Co-authored-by: pasta Co-authored-by: UdjinM6 --- src/evo/deterministicmns.cpp | 52 ++++++++- src/evo/deterministicmns.h | 2 + test/functional/feature_dip3_v19.py | 159 ++++++++++++++++++++++++++++ test/functional/test_runner.py | 1 + 4 files changed, 213 insertions(+), 1 deletion(-) create mode 100755 test/functional/feature_dip3_v19.py diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 5557ee9186..ecea6e0dd1 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -435,6 +435,48 @@ CDeterministicMNList CDeterministicMNList::ApplyDiff(const CBlockIndex* pindex, return result; } +// RepopulateUniquePropertyMap clears internal mnUniquePropertyMap, and repopulate it with currently MNs unique properties. +// This is needed when the v19 fork activates, we need to store again pubKeyOperator in the mnUniquePropertyMap. +// pubKeyOperator don't differ between the two schemes (legacy and basic(v19)) but their serialisation do: hence their hash. +// And because mnUniquePropertyMap store only hashes, then we need to re-calculate hashes and repopulate. +void CDeterministicMNList::RepopulateUniquePropertyMap() { + decltype(mnUniquePropertyMap) mnUniquePropertyMapEmpty; + mnUniquePropertyMap = mnUniquePropertyMapEmpty; + + for (const auto &p: mnMap) { + auto dmn = p.second; + if (!AddUniqueProperty(*dmn, dmn->collateralOutpoint)) { + throw (std::runtime_error( + strprintf("%s: Can't add a masternode %s with a duplicate collateralOutpoint=%s", __func__, + dmn->proTxHash.ToString(), dmn->collateralOutpoint.ToStringShort()))); + } + if (dmn->pdmnState->addr != CService() && !AddUniqueProperty(*dmn, dmn->pdmnState->addr)) { + throw (std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate address=%s", __func__, + dmn->proTxHash.ToString(), + dmn->pdmnState->addr.ToStringIPPort(false)))); + } + if (!AddUniqueProperty(*dmn, dmn->pdmnState->keyIDOwner)) { + throw (std::runtime_error( + strprintf("%s: Can't add a masternode %s with a duplicate keyIDOwner=%s", __func__, + dmn->proTxHash.ToString(), EncodeDestination(PKHash(dmn->pdmnState->keyIDOwner))))); + } + if (dmn->pdmnState->pubKeyOperator.Get().IsValid() && + !AddUniqueProperty(*dmn, dmn->pdmnState->pubKeyOperator)) { + throw (std::runtime_error( + strprintf("%s: Can't add a masternode %s with a duplicate pubKeyOperator=%s", __func__, + dmn->proTxHash.ToString(), dmn->pdmnState->pubKeyOperator.Get().ToString()))); + } + + if (dmn->nType == MnType::HighPerformance) { + if (!AddUniqueProperty(*dmn, dmn->pdmnState->platformNodeID)) { + throw (std::runtime_error( + strprintf("%s: Can't add a masternode %s with a duplicate platformNodeID=%s", __func__, + dmn->proTxHash.ToString(), dmn->pdmnState->platformNodeID.ToString()))); + } + } + } +} + void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn, bool fBumpTotalCount) { assert(dmn != nullptr); @@ -617,11 +659,19 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockInde newList.SetBlockHash(block.GetHash()); + // If the fork is active for pindex block, then we need to repopulate property map + // (Check documentation of CDeterministicMNList::RepopulateUniquePropertyMap()). + // This is needed only when base list is pre-v19 fork and pindex is post-v19 fork. + bool v19_just_activated = pindex == llmq::utils::V19ActivationIndex(pindex); + if (v19_just_activated) { + newList.RepopulateUniquePropertyMap(); + } + oldList = GetListForBlock(pindex->pprev); diff = oldList.BuildDiff(newList); m_evoDb.Write(std::make_pair(DB_LIST_DIFF, newList.GetBlockHash()), diff); - if ((nHeight % DISK_SNAPSHOT_PERIOD) == 0 || oldList.GetHeight() == -1) { + if ((nHeight % DISK_SNAPSHOT_PERIOD) == 0 || oldList.GetHeight() == -1 || v19_just_activated) { m_evoDb.Write(std::make_pair(DB_LIST_SNAPSHOT, newList.GetBlockHash()), newList); mnListsCache.emplace(newList.GetBlockHash(), newList); LogPrintf("CDeterministicMNManager::%s -- Wrote snapshot. nHeight=%d, mapCurMNs.allMNsCount=%d\n", diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index a0eb19c60d..bd7f74d15f 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -375,6 +375,8 @@ public: [[nodiscard]] CSimplifiedMNListDiff BuildSimplifiedDiff(const CDeterministicMNList& to, bool extended) const; [[nodiscard]] CDeterministicMNList ApplyDiff(const CBlockIndex* pindex, const CDeterministicMNListDiff& diff) const; + void RepopulateUniquePropertyMap(); + void AddMN(const CDeterministicMNCPtr& dmn, bool fBumpTotalCount = true); void UpdateMN(const CDeterministicMN& oldDmn, const std::shared_ptr& pdmnState); void UpdateMN(const uint256& proTxHash, const std::shared_ptr& pdmnState); diff --git a/test/functional/feature_dip3_v19.py b/test/functional/feature_dip3_v19.py new file mode 100755 index 0000000000..5b6839dc4a --- /dev/null +++ b/test/functional/feature_dip3_v19.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python3 +# Copyright (c) 2015-2022 The Dash Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +''' +feature_dip3_v19.py + +Checks DIP3 for v19 + +''' +from io import BytesIO + +from test_framework.mininode import P2PInterface +from test_framework.messages import CBlock, CBlockHeader, CCbTx, CMerkleBlock, FromHex, hash256, msg_getmnlistd, \ + QuorumId, ser_uint256 +from test_framework.test_framework import DashTestFramework +from test_framework.util import ( + assert_equal, wait_until +) + + +class TestP2PConn(P2PInterface): + def __init__(self): + super().__init__() + self.last_mnlistdiff = None + + def on_mnlistdiff(self, message): + self.last_mnlistdiff = message + + def wait_for_mnlistdiff(self, timeout=30): + def received_mnlistdiff(): + return self.last_mnlistdiff is not None + return wait_until(received_mnlistdiff, timeout=timeout) + + def getmnlistdiff(self, base_block_hash, block_hash): + msg = msg_getmnlistd(base_block_hash, block_hash) + self.last_mnlistdiff = None + self.send_message(msg) + self.wait_for_mnlistdiff() + return self.last_mnlistdiff + + +class DIP3V19Test(DashTestFramework): + def set_test_params(self): + self.set_dash_test_params(6, 5, fast_dip3_enforcement=True) + + def run_test(self): + # Connect all nodes to node1 so that we always have the whole network connected + # Otherwise only masternode connections will be established between nodes, which won't propagate TXs/blocks + # Usually node0 is the one that does this, but in this test we isolate it multiple times + + self.test_node = self.nodes[0].add_p2p_connection(TestP2PConn()) + null_hash = format(0, "064x") + + for i in range(len(self.nodes)): + if i != 0: + self.connect_nodes(i, 0) + + self.activate_dip8() + + self.nodes[0].sporkupdate("SPORK_17_QUORUM_DKG_ENABLED", 0) + self.wait_for_sporks_same() + + expected_updated = [mn.proTxHash for mn in self.mninfo] + b_0 = self.nodes[0].getbestblockhash() + self.test_getmnlistdiff(null_hash, b_0, {}, [], expected_updated) + + self.activate_v19(expected_activation_height=900) + self.log.info("Activated v19 at height:" + str(self.nodes[0].getblockcount())) + + self.move_to_next_cycle() + self.log.info("Cycle H height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+C height:" + str(self.nodes[0].getblockcount())) + self.move_to_next_cycle() + self.log.info("Cycle H+2C height:" + str(self.nodes[0].getblockcount())) + + self.mine_cycle_quorum(llmq_type_name='llmq_test_dip0024', llmq_type=103) + + revoke_protx = self.mninfo[-1].proTxHash + revoke_keyoperator = self.mninfo[-1].keyOperator + self.log.info(f"Trying to revoke proTx:{revoke_protx}") + self.test_revoke_protx(revoke_protx, revoke_keyoperator) + + self.mine_quorum(llmq_type_name='llmq_test', llmq_type=100) + + return + + def test_revoke_protx(self, revoke_protx, revoke_keyoperator): + funds_address = self.nodes[0].getnewaddress() + self.nodes[0].sendtoaddress(funds_address, 1) + self.nodes[0].generate(1) + self.sync_all(self.nodes) + + self.nodes[0].protx('revoke', revoke_protx, revoke_keyoperator, 1, funds_address) + self.nodes[0].generate(1) + self.sync_all(self.nodes) + self.log.info(f"Succesfully revoked={revoke_protx}") + for mn in self.mninfo: + if mn.proTxHash == revoke_protx: + self.mninfo.remove(mn) + return + + def test_getmnlistdiff(self, base_block_hash, block_hash, base_mn_list, expected_deleted, expected_updated): + d = self.test_getmnlistdiff_base(base_block_hash, block_hash) + + # Assert that the deletedMNs and mnList fields are what we expected + assert_equal(set(d.deletedMNs), set([int(e, 16) for e in expected_deleted])) + assert_equal(set([e.proRegTxHash for e in d.mnList]), set(int(e, 16) for e in expected_updated)) + + # Build a new list based on the old list and the info from the diff + new_mn_list = base_mn_list.copy() + for e in d.deletedMNs: + new_mn_list.pop(format(e, '064x')) + for e in d.mnList: + new_mn_list[format(e.proRegTxHash, '064x')] = e + + cbtx = CCbTx() + cbtx.deserialize(BytesIO(d.cbTx.vExtraPayload)) + + # Verify that the merkle root matches what we locally calculate + hashes = [] + for mn in sorted(new_mn_list.values(), key=lambda mn: ser_uint256(mn.proRegTxHash)): + hashes.append(hash256(mn.serialize())) + merkle_root = CBlock.get_merkle_root(hashes) + assert_equal(merkle_root, cbtx.merkleRootMNList) + + return new_mn_list + + def test_getmnlistdiff_base(self, base_block_hash, block_hash): + hexstr = self.nodes[0].getblockheader(block_hash, False) + header = FromHex(CBlockHeader(), hexstr) + + d = self.test_node.getmnlistdiff(int(base_block_hash, 16), int(block_hash, 16)) + assert_equal(d.baseBlockHash, int(base_block_hash, 16)) + assert_equal(d.blockHash, int(block_hash, 16)) + + # Check that the merkle proof is valid + proof = CMerkleBlock(header, d.merkleProof) + proof = proof.serialize().hex() + assert_equal(self.nodes[0].verifytxoutproof(proof), [d.cbTx.hash]) + + # Check if P2P messages match with RPCs + d2 = self.nodes[0].protx("diff", base_block_hash, block_hash) + assert_equal(d2["baseBlockHash"], base_block_hash) + assert_equal(d2["blockHash"], block_hash) + assert_equal(d2["cbTxMerkleTree"], d.merkleProof.serialize().hex()) + assert_equal(d2["cbTx"], d.cbTx.serialize().hex()) + assert_equal(set([int(e, 16) for e in d2["deletedMNs"]]), set(d.deletedMNs)) + assert_equal(set([int(e["proRegTxHash"], 16) for e in d2["mnList"]]), set([e.proRegTxHash for e in d.mnList])) + assert_equal(set([QuorumId(e["llmqType"], int(e["quorumHash"], 16)) for e in d2["deletedQuorums"]]), set(d.deletedQuorums)) + assert_equal(set([QuorumId(e["llmqType"], int(e["quorumHash"], 16)) for e in d2["newQuorums"]]), set([QuorumId(e.llmqType, e.quorumHash) for e in d.newQuorums])) + + return d + + +if __name__ == '__main__': + DIP3V19Test().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 474da55260..f2fac09566 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -106,6 +106,7 @@ BASE_SCRIPTS = [ 'wallet_dump.py', 'wallet_listtransactions.py', 'feature_multikeysporks.py', + 'feature_dip3_v19.py', 'feature_llmq_signing.py', # NOTE: needs dash_hash to pass 'feature_llmq_signing.py --spork21', # NOTE: needs dash_hash to pass 'feature_llmq_chainlocks.py', # NOTE: needs dash_hash to pass From 5f26a7b85c33e7d77c363a0bdcdc93681168fc64 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Thu, 9 Mar 2023 10:13:00 +0200 Subject: [PATCH 19/63] fix: BLS checkMalleable protection (#5240) ## Issue being fixed or feature implemented ## What was done? ## How Has This Been Tested? ## Breaking Changes ## Checklist: - [x] I have performed a self-review of my own code - [x] 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --------- Co-authored-by: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> --- src/bls/bls.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/bls/bls.h b/src/bls/bls.h index a74158f6e9..b74efd33fd 100644 --- a/src/bls/bls.h +++ b/src/bls/bls.h @@ -190,7 +190,17 @@ public: SetByteVector(vecBytes, specificLegacyScheme); if (checkMalleable && !CheckMalleable(vecBytes, specificLegacyScheme)) { - throw std::ios_base::failure("malleable BLS object"); + // If CheckMalleable failed with specificLegacyScheme, we need to try again with the opposite scheme. + // Probably we received the BLS object sent with legacy scheme, but in the meanwhile the fork activated. + SetByteVector(vecBytes, !specificLegacyScheme); + if (!CheckMalleable(vecBytes, !specificLegacyScheme)) { + // Both attempts failed + throw std::ios_base::failure("malleable BLS object"); + } else { + // Indeed the received vecBytes was in opposite scheme. But we can't keep it (mixing with the new scheme will lead to undefined behavior) + // Therefore, resetting current object (basically marking it as invalid). + Reset(); + } } } From adcd52e6782476017f3dfb2657ea3cf59b2af840 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Sat, 11 Mar 2023 19:43:33 +0200 Subject: [PATCH 20/63] chore(rpc): removed protx_revoke_legacy (#5241) ## Issue being fixed or feature implemented ## What was done? Removed protx_revoke_legacy since it required a BLS secret key and not a BLS public key. (BLS scheme is not applicable to secret keys) ## How Has This Been Tested? ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/rpc/evo.cpp | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/src/rpc/evo.cpp b/src/rpc/evo.cpp index 02122abb34..05c70a4e79 100644 --- a/src/rpc/evo.cpp +++ b/src/rpc/evo.cpp @@ -1126,7 +1126,7 @@ static void protx_revoke_help(const JSONRPCRequest& request) }.Check(request); } -static UniValue protx_revoke_wrapper(const JSONRPCRequest& request, const bool specific_legacy_bls_scheme) +static UniValue protx_revoke(const JSONRPCRequest& request) { protx_revoke_help(request); @@ -1136,11 +1136,7 @@ static UniValue protx_revoke_wrapper(const JSONRPCRequest& request, const bool s EnsureWalletIsUnlocked(wallet.get()); CProUpRevTx ptx; - if (specific_legacy_bls_scheme) { - ptx.nVersion = CProUpRevTx::LEGACY_BLS_VERSION; - } else { - ptx.nVersion = CProUpRevTx::GetVersion(llmq::utils::IsV19Active(::ChainActive().Tip())); - } + ptx.nVersion = CProUpRevTx::GetVersion(llmq::utils::IsV19Active(::ChainActive().Tip())); ptx.proTxHash = ParseHashV(request.params[0], "proTxHash"); CBLSSecretKey keyOperator = ParseBLSSecretKey(request.params[1].get_str(), "operatorKey"); @@ -1191,15 +1187,6 @@ static UniValue protx_revoke_wrapper(const JSONRPCRequest& request, const bool s return SignAndSendSpecialTx(request, tx); } -static UniValue protx_revoke(const JSONRPCRequest& request) -{ - return protx_revoke_wrapper(request, false); -} - -static UniValue protx_revoke_legacy(const JSONRPCRequest& request) -{ - return protx_revoke_wrapper(request, true); -} #endif//ENABLE_WALLET static void protx_list_help(const JSONRPCRequest& request) @@ -1541,8 +1528,6 @@ static UniValue protx(const JSONRPCRequest& request) return protx_update_registrar_legacy(new_request); } else if (command == "protxrevoke") { return protx_revoke(new_request); - } else if (command == "protxrevoke_legacy") { - return protx_revoke_legacy(new_request); } else #endif if (command == "protxlist") { From 323b29054521ac79faa4713ce245c3a60472f2a8 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Sat, 11 Mar 2023 19:44:35 +0200 Subject: [PATCH 21/63] fix: governance correct sig check (#5242) ## Issue being fixed or feature implemented ## What was done? When verifying signature of `CGovernanceVote`/`CGovernanceObject` we need to use the active scheme. ## How Has This Been Tested? ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/bls/bls.cpp | 9 +++++++-- src/bls/bls.h | 2 +- src/governance/object.cpp | 2 +- src/governance/vote.cpp | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/bls/bls.cpp b/src/bls/bls.cpp index fc1965d21d..0d0b04451a 100644 --- a/src/bls/bls.cpp +++ b/src/bls/bls.cpp @@ -288,19 +288,24 @@ void CBLSSignature::SubInsecure(const CBLSSignature& o) cachedHash.SetNull(); } -bool CBLSSignature::VerifyInsecure(const CBLSPublicKey& pubKey, const uint256& hash) const +bool CBLSSignature::VerifyInsecure(const CBLSPublicKey& pubKey, const uint256& hash, const bool specificLegacyScheme) const { if (!IsValid() || !pubKey.IsValid()) { return false; } try { - return Scheme(bls::bls_legacy_scheme.load())->Verify(pubKey.impl, bls::Bytes(hash.begin(), hash.size()), impl); + return Scheme(specificLegacyScheme)->Verify(pubKey.impl, bls::Bytes(hash.begin(), hash.size()), impl); } catch (...) { return false; } } +bool CBLSSignature::VerifyInsecure(const CBLSPublicKey& pubKey, const uint256& hash) const +{ + return VerifyInsecure(pubKey, hash, bls::bls_legacy_scheme.load()); +} + bool CBLSSignature::VerifyInsecureAggregated(const std::vector& pubKeys, const std::vector& hashes) const { if (!IsValid()) { diff --git a/src/bls/bls.h b/src/bls/bls.h index b74efd33fd..b160df722a 100644 --- a/src/bls/bls.h +++ b/src/bls/bls.h @@ -368,7 +368,7 @@ public: static CBLSSignature AggregateSecure(const std::vector& sigs, const std::vector& pks, const uint256& hash); void SubInsecure(const CBLSSignature& o); - + [[nodiscard]] bool VerifyInsecure(const CBLSPublicKey& pubKey, const uint256& hash, const bool specificLegacyScheme) const; [[nodiscard]] bool VerifyInsecure(const CBLSPublicKey& pubKey, const uint256& hash) const; [[nodiscard]] bool VerifyInsecureAggregated(const std::vector& pubKeys, const std::vector& hashes) const; diff --git a/src/governance/object.cpp b/src/governance/object.cpp index 5bb57ff08b..61b1043355 100644 --- a/src/governance/object.cpp +++ b/src/governance/object.cpp @@ -318,7 +318,7 @@ bool CGovernanceObject::CheckSignature(const CBLSPublicKey& pubKey) const const auto pindex = llmq::utils::V19ActivationIndex(::ChainActive().Tip()); bool is_bls_legacy_scheme = pindex == nullptr || nTime < pindex->nTime; sig.SetByteVector(vchSig, is_bls_legacy_scheme); - if (!sig.VerifyInsecure(pubKey, GetSignatureHash())) { + if (!sig.VerifyInsecure(pubKey, GetSignatureHash(), is_bls_legacy_scheme)) { LogPrintf("CGovernanceObject::CheckSignature -- VerifyInsecure() failed\n"); return false; } diff --git a/src/governance/vote.cpp b/src/governance/vote.cpp index f5dd9beed9..8482ed29bc 100644 --- a/src/governance/vote.cpp +++ b/src/governance/vote.cpp @@ -240,7 +240,7 @@ bool CGovernanceVote::CheckSignature(const CBLSPublicKey& pubKey) const const auto pindex = llmq::utils::V19ActivationIndex(::ChainActive().Tip()); bool is_bls_legacy_scheme = pindex == nullptr || nTime < pindex->nTime; sig.SetByteVector(vchSig, is_bls_legacy_scheme); - if (!sig.VerifyInsecure(pubKey, GetSignatureHash())) { + if (!sig.VerifyInsecure(pubKey, GetSignatureHash(), is_bls_legacy_scheme)) { LogPrintf("CGovernanceVote::CheckSignature -- VerifyInsecure() failed\n"); return false; } From ee60e8a6c42b207ab37d9a9b938d6d2f8a56a674 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Sat, 11 Mar 2023 19:45:49 +0200 Subject: [PATCH 22/63] feat(rpc): Return HPMN fields (#5243) ## Issue being fixed or feature implemented HPMN fields were missing when selecting a HPMN in Masternodes tab of Qt client. ## What was done? Return HPMN fields in JSON reply of `CDeterministicMNState`. ## How Has This Been Tested? ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/evo/deterministicmns.cpp | 2 +- src/evo/dmnstate.cpp | 7 ++++++- src/evo/dmnstate.h | 2 +- src/rpc/masternode.cpp | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index ecea6e0dd1..079238ac6f 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -48,7 +48,7 @@ void CDeterministicMN::ToJson(UniValue& obj) const obj.setObject(); UniValue stateObj; - pdmnState->ToJson(stateObj); + pdmnState->ToJson(stateObj, nType); obj.pushKV("type", std::string(GetMnType(nType).description)); obj.pushKV("proTxHash", proTxHash.ToString()); diff --git a/src/evo/dmnstate.cpp b/src/evo/dmnstate.cpp index 267c3148da..7cbdf373aa 100644 --- a/src/evo/dmnstate.cpp +++ b/src/evo/dmnstate.cpp @@ -32,7 +32,7 @@ std::string CDeterministicMNState::ToString() const EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.Get().ToString(), EncodeDestination(PKHash(keyIDVoting)), addr.ToStringIPPort(false), payoutAddress, operatorPayoutAddress); } -void CDeterministicMNState::ToJson(UniValue& obj) const +void CDeterministicMNState::ToJson(UniValue& obj, MnType nType) const { obj.clear(); obj.setObject(); @@ -46,6 +46,11 @@ void CDeterministicMNState::ToJson(UniValue& obj) const obj.pushKV("revocationReason", nRevocationReason); obj.pushKV("ownerAddress", EncodeDestination(PKHash(keyIDOwner))); obj.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting))); + if (nType == MnType::HighPerformance) { + obj.pushKV("platformNodeID", platformNodeID.ToString()); + obj.pushKV("platformP2PPort", platformP2PPort); + obj.pushKV("platformHTTPPort", platformHTTPPort); + } CTxDestination dest; if (ExtractDestination(scriptPayout, dest)) { diff --git a/src/evo/dmnstate.h b/src/evo/dmnstate.h index e772a4e892..9f3aa52084 100644 --- a/src/evo/dmnstate.h +++ b/src/evo/dmnstate.h @@ -200,7 +200,7 @@ public: public: std::string ToString() const; - void ToJson(UniValue& obj) const; + void ToJson(UniValue& obj, MnType nType) const; }; class CDeterministicMNStateDiff diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 8f8c22fbdd..7d4fbb2473 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -268,7 +268,7 @@ static UniValue masternode_status(const JSONRPCRequest& request) mnObj.pushKV("collateralHash", dmn->collateralOutpoint.hash.ToString()); mnObj.pushKV("collateralIndex", (int)dmn->collateralOutpoint.n); UniValue stateObj; - dmn->pdmnState->ToJson(stateObj); + dmn->pdmnState->ToJson(stateObj, dmn->nType); mnObj.pushKV("dmnState", stateObj); } mnObj.pushKV("state", activeMasternodeManager->GetStateString()); From bb4a1add2cbad81d03b91fb5ff013fcb56be3af1 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Mon, 13 Mar 2023 18:12:09 +0200 Subject: [PATCH 23/63] feat: Bumped v19 start time for v19 (#5244) ## Issue being fixed or feature implemented Delayed activation to reexperience rc.6 ## What was done? ## How Has This Been Tested? ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/chainparams.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 0945f964c4..5cf3f5fcdd 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -486,7 +486,7 @@ public: // Deployment of Deployment of Basic BLS, AssetLocks, EHF consensus.vDeployments[Consensus::DEPLOYMENT_V19].bit = 8; - consensus.vDeployments[Consensus::DEPLOYMENT_V19].nStartTime = 1678060800; // Tue, March 06, 2023 0:00:00 + consensus.vDeployments[Consensus::DEPLOYMENT_V19].nStartTime = 1678838400; // Wed, March 15, 2023 0:00:00 consensus.vDeployments[Consensus::DEPLOYMENT_V19].nTimeout = 999999999999ULL; consensus.vDeployments[Consensus::DEPLOYMENT_V19].nWindowSize = 100; consensus.vDeployments[Consensus::DEPLOYMENT_V19].nThresholdStart = 80; // 80% of 100 From b428c55db8da5829703f7bc3d36af81954d628be Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Mon, 13 Mar 2023 19:11:17 +0300 Subject: [PATCH 24/63] refactor: tweak GetLLMQ to fail gracefully and let caller handle results accordingly (#5247) This allows us to have a bit more granular control over GetLLMQ results, removes code duplication and also optimises things a tiny bit by replacing "HasLLMQ + GetLLMQParams" calls with simply "GetLLMQParams". Use `optional` in `GetLLMQ`, drop `HasLLMQ`. run tests, reindex on testnet/mainnet n/a - [x] I have performed a self-review of my own code - [x] 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/chainparams.cpp | 39 ++++++++++++++-------------- src/chainparams.h | 3 +-- src/evo/cbtx.cpp | 17 +++++++++---- src/evo/deterministicmns.cpp | 7 ++++-- src/evo/mnhftx.cpp | 6 +++-- src/llmq/blockprocessor.cpp | 46 +++++++++++++++++++++++----------- src/llmq/commitment.cpp | 34 ++++++++++++++----------- src/llmq/debug.cpp | 7 +++--- src/llmq/dkgsession.cpp | 4 +-- src/llmq/dkgsession.h | 2 +- src/llmq/dkgsessionhandler.cpp | 2 +- src/llmq/dkgsessionhandler.h | 2 +- src/llmq/dkgsessionmgr.cpp | 11 ++++---- src/llmq/instantsend.cpp | 33 ++++++++++++++---------- src/llmq/instantsend.h | 2 +- src/llmq/params.h | 5 ++++ src/llmq/quorums.cpp | 14 +++++++---- src/llmq/quorums.h | 2 +- src/llmq/signing.cpp | 24 ++++++++++-------- src/llmq/signing.h | 2 +- src/llmq/signing_shares.cpp | 17 +++++++++---- src/llmq/snapshot.cpp | 8 +++--- src/llmq/utils.cpp | 29 ++++++++++++--------- src/llmq/utils.h | 4 +-- src/rpc/quorums.cpp | 42 +++++++++++++++++++------------ 25 files changed, 221 insertions(+), 141 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 5cf3f5fcdd..6ba180563d 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -107,7 +107,7 @@ static CBlock FindDevNetGenesisBlock(const CBlock &prevBlock, const CAmount& rew void CChainParams::AddLLMQ(Consensus::LLMQType llmqType) { - assert(!HasLLMQ(llmqType)); + assert(!GetLLMQ(llmqType).has_value()); for (const auto& llmq_param : Consensus::available_llmqs) { if (llmq_param.type == llmqType) { consensus.llmqs.push_back(llmq_param); @@ -118,25 +118,14 @@ void CChainParams::AddLLMQ(Consensus::LLMQType llmqType) assert(false); } -const Consensus::LLMQParams& CChainParams::GetLLMQ(Consensus::LLMQType llmqType) const +std::optional CChainParams::GetLLMQ(Consensus::LLMQType llmqType) const { for (const auto& llmq_param : consensus.llmqs) { if (llmq_param.type == llmqType) { - return llmq_param; + return std::make_optional(llmq_param); } } - error("CChainParams::%s: unknown LLMQ type %d", __func__, static_cast(llmqType)); - assert(false); -} - -bool CChainParams::HasLLMQ(Consensus::LLMQType llmqType) const -{ - for (const auto& llmq_param : consensus.llmqs) { - if (llmq_param.type == llmqType) { - return true; - } - } - return false; + return std::nullopt; } /** @@ -1279,7 +1268,10 @@ void CDevNetParams::UpdateDevnetLLMQChainLocksFromArgs(const ArgsManager& args) { if (!args.IsArgSet("-llmqchainlocks")) return; - std::string strLLMQType = gArgs.GetArg("-llmqchainlocks", std::string(GetLLMQ(consensus.llmqTypeChainLocks).name)); + const auto& llmq_params_opt = GetLLMQ(consensus.llmqTypeChainLocks); + assert(llmq_params_opt.has_value()); + + std::string strLLMQType = gArgs.GetArg("-llmqchainlocks", std::string(llmq_params_opt->name)); Consensus::LLMQType llmqType = Consensus::LLMQType::LLMQ_NONE; for (const auto& params : consensus.llmqs) { @@ -1301,7 +1293,10 @@ void CDevNetParams::UpdateDevnetLLMQInstantSendFromArgs(const ArgsManager& args) { if (!args.IsArgSet("-llmqinstantsend")) return; - std::string strLLMQType = gArgs.GetArg("-llmqinstantsend", std::string(GetLLMQ(consensus.llmqTypeInstantSend).name)); + const auto& llmq_params_opt = GetLLMQ(consensus.llmqTypeInstantSend); + assert(llmq_params_opt.has_value()); + + std::string strLLMQType = gArgs.GetArg("-llmqinstantsend", std::string(llmq_params_opt->name)); Consensus::LLMQType llmqType = Consensus::LLMQType::LLMQ_NONE; for (const auto& params : consensus.llmqs) { @@ -1323,7 +1318,10 @@ void CDevNetParams::UpdateDevnetLLMQInstantSendDIP0024FromArgs(const ArgsManager { if (!args.IsArgSet("-llmqinstantsenddip0024")) return; - std::string strLLMQType = gArgs.GetArg("-llmqinstantsenddip0024", std::string(GetLLMQ(consensus.llmqTypeDIP0024InstantSend).name)); + const auto& llmq_params_opt = GetLLMQ(consensus.llmqTypeDIP0024InstantSend); + assert(llmq_params_opt.has_value()); + + std::string strLLMQType = gArgs.GetArg("-llmqinstantsenddip0024", std::string(llmq_params_opt->name)); Consensus::LLMQType llmqType = Consensus::LLMQType::LLMQ_NONE; for (const auto& params : consensus.llmqs) { @@ -1345,7 +1343,10 @@ void CDevNetParams::UpdateDevnetLLMQPlatformFromArgs(const ArgsManager& args) { if (!args.IsArgSet("-llmqplatform")) return; - std::string strLLMQType = gArgs.GetArg("-llmqplatform", std::string(GetLLMQ(consensus.llmqTypePlatform).name)); + const auto& llmq_params_opt = GetLLMQ(consensus.llmqTypePlatform); + assert(llmq_params_opt.has_value()); + + std::string strLLMQType = gArgs.GetArg("-llmqplatform", std::string(llmq_params_opt->name)); Consensus::LLMQType llmqType = Consensus::LLMQType::LLMQ_NONE; for (const auto& params : consensus.llmqs) { diff --git a/src/chainparams.h b/src/chainparams.h index a0c8c7275f..b6b1cf7c03 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -112,8 +112,7 @@ public: const std::vector& SporkAddresses() const { return vSporkAddresses; } int MinSporkKeys() const { return nMinSporkKeys; } bool BIP9CheckMasternodesUpgraded() const { return fBIP9CheckMasternodesUpgraded; } - const Consensus::LLMQParams& GetLLMQ(Consensus::LLMQType llmqType) const; - bool HasLLMQ(Consensus::LLMQType llmqType) const; + std::optional GetLLMQ(Consensus::LLMQType llmqType) const; protected: CChainParams() {} diff --git a/src/evo/cbtx.cpp b/src/evo/cbtx.cpp index bea646f79b..8f4b4fb60c 100644 --- a/src/evo/cbtx.cpp +++ b/src/evo/cbtx.cpp @@ -189,7 +189,9 @@ auto CachedGetQcHashesQcIndexedHashes(const CBlockIndex* pindexPrev, const llmq: qcIndexedHashes_cached.clear(); for (const auto& [llmqType, vecBlockIndexes] : quorums) { - bool rotation_enabled = llmq::utils::IsQuorumRotationEnabled(llmqType, pindexPrev); + const auto& llmq_params_opt = llmq::GetLLMQParams(llmqType); + assert(llmq_params_opt.has_value()); + bool rotation_enabled = llmq::utils::IsQuorumRotationEnabled(llmq_params_opt.value(), pindexPrev); auto& vec_hashes = qcHashes_cached[llmqType]; vec_hashes.reserve(vecBlockIndexes.size()); auto& map_indexed_hashes = qcIndexedHashes_cached[llmqType]; @@ -253,12 +255,16 @@ bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPre // having null commitments is ok but we don't use them here, move to the next tx continue; } + const auto& llmq_params_opt = llmq::GetLLMQParams(qc.commitment.llmqType); + if (!llmq_params_opt.has_value()) { + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-qc-commitment-type-calc-cbtx-quorummerkleroot"); + } + const auto& llmq_params = llmq_params_opt.value(); auto qcHash = ::SerializeHash(qc.commitment); - if (llmq::utils::IsQuorumRotationEnabled(qc.commitment.llmqType, pindexPrev)) { + if (llmq::utils::IsQuorumRotationEnabled(llmq_params, pindexPrev)) { auto& map_indexed_hashes = qcIndexedHashes[qc.commitment.llmqType]; map_indexed_hashes[qc.commitment.quorumIndex] = qcHash; } else { - const auto& llmq_params = llmq::GetLLMQParams(qc.commitment.llmqType); auto& vec_hashes = qcHashes[llmq_params.type]; if (vec_hashes.size() == size_t(llmq_params.signingActiveQuorumCount)) { // we pop the last entry, which is actually the oldest quorum as GetMinedAndActiveCommitmentsUntilBlock @@ -282,8 +288,9 @@ bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPre vec_hashes_final.reserve(CalcHashCountFromQCHashes(qcHashes)); for (const auto& [llmqType, vec_hashes] : qcHashes) { - const auto& llmq_params = llmq::GetLLMQParams(llmqType); - if (vec_hashes.size() > size_t(llmq_params.signingActiveQuorumCount)) { + const auto& llmq_params_opt = llmq::GetLLMQParams(llmqType); + assert(llmq_params_opt.has_value()); + if (vec_hashes.size() > size_t(llmq_params_opt->signingActiveQuorumCount)) { return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "excess-quorums-calc-cbtx-quorummerkleroot"); } // Copy vec_hashes into vec_hashes_final diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 079238ac6f..ef84168498 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -954,9 +954,12 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-qc-payload"); } if (!qc.commitment.IsNull()) { - const auto& llmq_params = llmq::GetLLMQParams(qc.commitment.llmqType); + const auto& llmq_params_opt = llmq::GetLLMQParams(qc.commitment.llmqType); + if (!llmq_params_opt.has_value()) { + return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-qc-commitment-type"); + } int qcnHeight = int(qc.nHeight); - int quorumHeight = qcnHeight - (qcnHeight % llmq_params.dkgInterval) + int(qc.commitment.quorumIndex); + int quorumHeight = qcnHeight - (qcnHeight % llmq_params_opt->dkgInterval) + int(qc.commitment.quorumIndex); auto pQuorumBaseBlockIndex = pindexPrev->GetAncestor(quorumHeight); if (!pQuorumBaseBlockIndex || pQuorumBaseBlockIndex->GetBlockHash() != qc.commitment.quorumHash) { // we should actually never get into this case as validation should have caught it...but let's be sure diff --git a/src/evo/mnhftx.cpp b/src/evo/mnhftx.cpp index 2cac956cdc..d3b86dc4be 100644 --- a/src/evo/mnhftx.cpp +++ b/src/evo/mnhftx.cpp @@ -25,7 +25,9 @@ bool MNHFTx::Verify(const CBlockIndex* pQuorumIndex) const } Consensus::LLMQType llmqType = Params().GetConsensus().llmqTypeMnhf; - int signOffset{llmq::GetLLMQParams(llmqType).dkgInterval}; + const auto& llmq_params_opt = llmq::GetLLMQParams(llmqType); + assert(llmq_params_opt.has_value()); + int signOffset{llmq_params_opt->dkgInterval}; const uint256 requestId = ::SerializeHash(std::make_pair(CBLSIG_REQUESTID_PREFIX, pQuorumIndex->nHeight)); return llmq::CSigningManager::VerifyRecoveredSig(llmqType, *llmq::quorumManager, pQuorumIndex->nHeight, requestId, pQuorumIndex->GetBlockHash(), sig, 0) || @@ -53,7 +55,7 @@ bool CheckMNHFTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidat return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-mnhf-quorum-hash"); } - if (!Params().HasLLMQ(Params().GetConsensus().llmqTypeMnhf)) { + if (!llmq::GetLLMQParams(Params().GetConsensus().llmqTypeMnhf).has_value()) { return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-mnhf-type"); } diff --git a/src/llmq/blockprocessor.cpp b/src/llmq/blockprocessor.cpp index 46e233239e..323884fb77 100644 --- a/src/llmq/blockprocessor.cpp +++ b/src/llmq/blockprocessor.cpp @@ -59,7 +59,8 @@ void CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_view m return; } - if (!Params().HasLLMQ(qc.llmqType)) { + const auto& llmq_params_opt = GetLLMQParams(qc.llmqType); + if (!llmq_params_opt.has_value()) { LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- invalid commitment type %d from peer=%d\n", __func__, ToUnderlying(qc.llmqType), peer.GetId()); WITH_LOCK(cs_main, Misbehaving(peer.GetId(), 100)); @@ -85,14 +86,14 @@ void CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_view m // same, can't punish return; } - int quorumHeight = pQuorumBaseBlockIndex->nHeight - (pQuorumBaseBlockIndex->nHeight % GetLLMQParams(type).dkgInterval) + int(qc.quorumIndex); + int quorumHeight = pQuorumBaseBlockIndex->nHeight - (pQuorumBaseBlockIndex->nHeight % llmq_params_opt->dkgInterval) + int(qc.quorumIndex); if (quorumHeight != pQuorumBaseBlockIndex->nHeight) { LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- block %s is not the first block in the DKG interval, peer=%d\n", __func__, qc.quorumHash.ToString(), peer.GetId()); Misbehaving(peer.GetId(), 100); return; } - if (pQuorumBaseBlockIndex->nHeight < (::ChainActive().Height() - GetLLMQParams(type).dkgInterval)) { + if (pQuorumBaseBlockIndex->nHeight < (::ChainActive().Height() - llmq_params_opt->dkgInterval)) { LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- block %s is too old, peer=%d\n", __func__, qc.quorumHash.ToString(), peer.GetId()); // TODO: enable punishment in some future version when all/most nodes are running with this fix @@ -177,7 +178,7 @@ bool CQuorumBlockProcessor::ProcessBlock(const CBlock& block, const CBlockIndex* if (numCommitmentsRequired > numCommitmentsInNewBlock) { return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-qc-missing"); } - if (llmq::utils::IsQuorumRotationEnabled(params.type, pindex)) { + if (llmq::utils::IsQuorumRotationEnabled(params, pindex)) { LogPrintf("[ProcessBlock] h[%d] numCommitmentsRequired[%d] numCommitmentsInNewBlock[%d]\n", pindex->nHeight, numCommitmentsRequired, numCommitmentsInNewBlock); } } @@ -213,7 +214,12 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH { AssertLockHeld(cs_main); - const auto& llmq_params = GetLLMQParams(qc.llmqType); + const auto& llmq_params_opt = GetLLMQParams(qc.llmqType); + if (!llmq_params_opt.has_value()) { + LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- invalid commitment type %d\n", __func__, ToUnderlying(qc.llmqType)); + return false; + } + const auto& llmq_params = llmq_params_opt.value(); uint256 quorumHash = GetQuorumBlockHash(llmq_params, nHeight, qc.quorumIndex); @@ -267,7 +273,7 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH return true; } - bool rotation_enabled = utils::IsQuorumRotationEnabled(llmq_params.type, pQuorumBaseBlockIndex); + bool rotation_enabled = utils::IsQuorumRotationEnabled(llmq_params, pQuorumBaseBlockIndex); if (rotation_enabled) { LogPrint(BCLog::LLMQ, "[ProcessCommitment] height[%d] pQuorumBaseBlockIndex[%d] quorumIndex[%d] qversion[%d] Built\n", @@ -320,7 +326,10 @@ bool CQuorumBlockProcessor::UndoBlock(const CBlock& block, const CBlockIndex* pi m_evoDb.Erase(std::make_pair(DB_MINED_COMMITMENT, std::make_pair(qc.llmqType, qc.quorumHash))); - if (llmq::utils::IsQuorumRotationEnabled(qc.llmqType, pindex)) { + const auto& llmq_params_opt = GetLLMQParams(qc.llmqType); + assert(llmq_params_opt.has_value()); + + if (llmq::utils::IsQuorumRotationEnabled(llmq_params_opt.value(), pindex)) { m_evoDb.Erase(BuildInversedHeightKeyIndexed(qc.llmqType, pindex->nHeight, int(qc.quorumIndex))); } else { m_evoDb.Erase(BuildInversedHeightKey(qc.llmqType, pindex->nHeight)); @@ -379,7 +388,9 @@ bool CQuorumBlockProcessor::UpgradeDB() } const auto* pQuorumBaseBlockIndex = LookupBlockIndex(qc.quorumHash); m_evoDb.GetRawDB().Write(std::make_pair(DB_MINED_COMMITMENT, std::make_pair(qc.llmqType, qc.quorumHash)), std::make_pair(qc, pindex->GetBlockHash())); - if (llmq::utils::IsQuorumRotationEnabled(qc.llmqType, pQuorumBaseBlockIndex)) { + const auto& llmq_params_opt = GetLLMQParams(qc.llmqType); + assert(llmq_params_opt.has_value()); + if (llmq::utils::IsQuorumRotationEnabled(llmq_params_opt.value(), pQuorumBaseBlockIndex)) { m_evoDb.GetRawDB().Write(BuildInversedHeightKeyIndexed(qc.llmqType, pindex->nHeight, int(qc.quorumIndex)), pQuorumBaseBlockIndex->nHeight); } else { m_evoDb.GetRawDB().Write(BuildInversedHeightKey(qc.llmqType, pindex->nHeight), pQuorumBaseBlockIndex->nHeight); @@ -413,8 +424,14 @@ bool CQuorumBlockProcessor::GetCommitmentsFromBlock(const CBlock& block, const C return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-qc-payload"); } + const auto& llmq_params_opt = GetLLMQParams(qc.commitment.llmqType); + if (!llmq_params_opt.has_value()) { + // should not happen as it was verified before processing the block + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-qc-commitment-type"); + } + // only allow one commitment per type and per block (This was changed with rotation) - if (!utils::IsQuorumRotationEnabled(qc.commitment.llmqType, pindex)) { + if (!utils::IsQuorumRotationEnabled(llmq_params_opt.value(), pindex)) { if (ret.count(qc.commitment.llmqType) != 0) { return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-qc-dup"); } @@ -461,7 +478,7 @@ size_t CQuorumBlockProcessor::GetNumCommitmentsRequired(const Consensus::LLMQPar assert(nHeight <= ::ChainActive().Height() + 1); const auto *const pindex = ::ChainActive().Height() < nHeight ? ::ChainActive().Tip() : ::ChainActive().Tip()->GetAncestor(nHeight); - bool rotation_enabled = utils::IsQuorumRotationEnabled(llmqParams.type, pindex); + bool rotation_enabled = utils::IsQuorumRotationEnabled(llmqParams, pindex); size_t quorums_num = rotation_enabled ? llmqParams.signingActiveQuorumCount : 1; size_t ret{0}; @@ -614,10 +631,11 @@ std::optional CQuorumBlockProcessor::GetLastMinedCommitments std::vector> CQuorumBlockProcessor::GetLastMinedCommitmentsPerQuorumIndexUntilBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex, size_t cycle) const { - const Consensus::LLMQParams& llmqParams = GetLLMQParams(llmqType); + const auto& llmq_params_opt = GetLLMQParams(llmqType); + assert(llmq_params_opt.has_value()); std::vector> ret; - for (const auto quorumIndex : irange::range(llmqParams.signingActiveQuorumCount)) { + for (const auto quorumIndex : irange::range(llmq_params_opt->signingActiveQuorumCount)) { std::optional q = GetLastMinedCommitmentsByQuorumIndexUntilBlock(llmqType, pindex, quorumIndex, cycle); if (q.has_value()) { ret.emplace_back(quorumIndex, q.value()); @@ -665,7 +683,7 @@ std::map> CQuorumBlockProce for (const auto& params : Params().GetConsensus().llmqs) { auto& v = ret[params.type]; v.reserve(params.signingActiveQuorumCount); - if (utils::IsQuorumRotationEnabled(params.type, pindex)) { + if (utils::IsQuorumRotationEnabled(params, pindex)) { std::vector> commitments = GetLastMinedCommitmentsPerQuorumIndexUntilBlock(params.type, pindex, 0); std::transform(commitments.begin(), commitments.end(), std::back_inserter(v), [](const std::pair& p) { return p.second; }); @@ -744,7 +762,7 @@ std::optional> CQuorumBlockProcessor::GetMineableC assert(nHeight <= ::ChainActive().Height() + 1); const auto *const pindex = ::ChainActive().Height() < nHeight ? ::ChainActive().Tip() : ::ChainActive().Tip()->GetAncestor(nHeight); - bool rotation_enabled = utils::IsQuorumRotationEnabled(llmqParams.type, pindex); + bool rotation_enabled = utils::IsQuorumRotationEnabled(llmqParams, pindex); bool basic_bls_enabled = utils::IsV19Active(pindex); size_t quorums_num = rotation_enabled ? llmqParams.signingActiveQuorumCount : 1; diff --git a/src/llmq/commitment.cpp b/src/llmq/commitment.cpp index 3c2f72a225..91c1bb2db9 100644 --- a/src/llmq/commitment.cpp +++ b/src/llmq/commitment.cpp @@ -34,8 +34,15 @@ void LogPrintfFinalCommitment(Types... out) { bool CFinalCommitment::Verify(const CBlockIndex* pQuorumBaseBlockIndex, bool checkSigs) const { + const auto& llmq_params_opt = GetLLMQParams(llmqType); + if (!llmq_params_opt.has_value()) { + LogPrintfFinalCommitment("q[%s] invalid llmqType=%d\n", quorumHash.ToString(), ToUnderlying(llmqType)); + return false; + } + const auto& llmq_params = llmq_params_opt.value(); + uint16_t expected_nversion{CFinalCommitment::LEGACY_BLS_NON_INDEXED_QUORUM_VERSION}; - if (utils::IsQuorumRotationEnabled(llmqType, pQuorumBaseBlockIndex)) { + if (utils::IsQuorumRotationEnabled(llmq_params, pQuorumBaseBlockIndex)) { expected_nversion = utils::IsV19Active(pQuorumBaseBlockIndex) ? CFinalCommitment::BASIC_BLS_INDEXED_QUORUM_VERSION : CFinalCommitment::LEGACY_BLS_INDEXED_QUORUM_VERSION; } else { @@ -46,12 +53,6 @@ bool CFinalCommitment::Verify(const CBlockIndex* pQuorumBaseBlockIndex, bool che return false; } - if (!Params().HasLLMQ(llmqType)) { - LogPrintfFinalCommitment("q[%s] invalid llmqType=%d\n", quorumHash.ToString(), ToUnderlying(llmqType)); - return false; - } - const auto& llmq_params = GetLLMQParams(llmqType); - if (pQuorumBaseBlockIndex->GetBlockHash() != quorumHash) { LogPrintfFinalCommitment("q[%s] invalid quorumHash\n", quorumHash.ToString()); return false; @@ -149,12 +150,13 @@ bool CFinalCommitment::Verify(const CBlockIndex* pQuorumBaseBlockIndex, bool che bool CFinalCommitment::VerifyNull() const { - if (!Params().HasLLMQ(llmqType)) { + const auto& llmq_params_opt = GetLLMQParams(llmqType); + if (!llmq_params_opt.has_value()) { LogPrintfFinalCommitment("q[%s]invalid llmqType=%d\n", quorumHash.ToString(), ToUnderlying(llmqType)); return false; } - if (!IsNull() || !VerifySizes(GetLLMQParams(llmqType))) { + if (!IsNull() || !VerifySizes(llmq_params_opt.value())) { return false; } @@ -181,10 +183,16 @@ bool CheckLLMQCommitment(const CTransaction& tx, const CBlockIndex* pindexPrev, LogPrintfFinalCommitment("h[%d] GetTxPayload failed\n", pindexPrev->nHeight); return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-qc-payload"); } - const auto& llmq_params = GetLLMQParams(qcTx.commitment.llmqType); + + const auto& llmq_params_opt = GetLLMQParams(qcTx.commitment.llmqType); + if (!llmq_params_opt.has_value()) { + LogPrintfFinalCommitment("h[%d] GetLLMQParams failed for llmqType[%d]\n", pindexPrev->nHeight, ToUnderlying(qcTx.commitment.llmqType)); + return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-qc-commitment-type"); + } + if (LogAcceptCategory(BCLog::LLMQ)) { std::stringstream ss; - for (const auto i: irange::range(llmq_params.size)) { + for (const auto i: irange::range(llmq_params_opt->size)) { ss << "v[" << i << "]=" << qcTx.commitment.validMembers[i]; } LogPrintfFinalCommitment("%s llmqType[%d] validMembers[%s] signers[]\n", __func__, @@ -212,10 +220,6 @@ bool CheckLLMQCommitment(const CTransaction& tx, const CBlockIndex* pindexPrev, return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-qc-quorum-hash"); } - if (!Params().HasLLMQ(qcTx.commitment.llmqType)) { - return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-qc-type"); - } - if (qcTx.commitment.IsNull()) { if (!qcTx.commitment.VerifyNull()) { LogPrintfFinalCommitment("h[%d] invalid qcTx.commitment[%s] VerifyNull failed\n", pindexPrev->nHeight, qcTx.commitment.quorumHash.ToString()); diff --git a/src/llmq/debug.cpp b/src/llmq/debug.cpp index 1f7608bdfa..003b977e5a 100644 --- a/src/llmq/debug.cpp +++ b/src/llmq/debug.cpp @@ -19,7 +19,7 @@ UniValue CDKGDebugSessionStatus::ToJson(int quorumIndex, int detailLevel) const { UniValue ret(UniValue::VOBJ); - if (!Params().HasLLMQ(llmqType) || quorumHash.IsNull()) { + if (!GetLLMQParams(llmqType).has_value() || quorumHash.IsNull()) { return ret; } @@ -118,11 +118,12 @@ UniValue CDKGDebugStatus::ToJson(int detailLevel) const // TODO Support array of sessions UniValue sessionsArrJson(UniValue::VARR); for (const auto& p : sessions) { - if (!Params().HasLLMQ(p.first.first)) { + const auto& llmq_params_opt = GetLLMQParams(p.first.first); + if (!llmq_params_opt.has_value()) { continue; } UniValue s(UniValue::VOBJ); - s.pushKV("llmqType", std::string(GetLLMQParams(p.first.first).name)); + s.pushKV("llmqType", std::string(llmq_params_opt->name)); s.pushKV("quorumIndex", p.first.second); s.pushKV("status", p.second.ToJson(p.first.second, detailLevel)); diff --git a/src/llmq/dkgsession.cpp b/src/llmq/dkgsession.cpp index 0c269daa67..e9d95c5084 100644 --- a/src/llmq/dkgsession.cpp +++ b/src/llmq/dkgsession.cpp @@ -86,7 +86,7 @@ bool CDKGSession::Init(const CBlockIndex* _pQuorumBaseBlockIndex, const std::vec CDKGLogger logger(*this, __func__); - if (LogAcceptCategory(BCLog::LLMQ) && utils::IsQuorumRotationEnabled(params.type, m_quorum_base_block_index)) { + if (LogAcceptCategory(BCLog::LLMQ) && utils::IsQuorumRotationEnabled(params, m_quorum_base_block_index)) { int cycleQuorumBaseHeight = m_quorum_base_block_index->nHeight - quorumIndex; const CBlockIndex* pCycleQuorumBaseBlockIndex = m_quorum_base_block_index->GetAncestor(cycleQuorumBaseHeight); std::stringstream ss; @@ -1207,7 +1207,7 @@ std::vector CDKGSession::FinalizeCommitments() fqc.quorumPublicKey = first.quorumPublicKey; fqc.quorumVvecHash = first.quorumVvecHash; - if (utils::IsQuorumRotationEnabled(fqc.llmqType, m_quorum_base_block_index)) { + if (utils::IsQuorumRotationEnabled(params, m_quorum_base_block_index)) { fqc.nVersion = utils::IsV19Active(m_quorum_base_block_index) ? CFinalCommitment::BASIC_BLS_INDEXED_QUORUM_VERSION : CFinalCommitment::LEGACY_BLS_INDEXED_QUORUM_VERSION; fqc.quorumIndex = quorumIndex; } else { diff --git a/src/llmq/dkgsession.h b/src/llmq/dkgsession.h index 90a82bec34..4d7f70c7ab 100644 --- a/src/llmq/dkgsession.h +++ b/src/llmq/dkgsession.h @@ -257,7 +257,7 @@ class CDKGSession friend class CDKGLogger; private: - const Consensus::LLMQParams& params; + const Consensus::LLMQParams params; CBLSWorker& blsWorker; CBLSWorkerCache cache; diff --git a/src/llmq/dkgsessionhandler.cpp b/src/llmq/dkgsessionhandler.cpp index 5c0cd46154..8645d8335b 100644 --- a/src/llmq/dkgsessionhandler.cpp +++ b/src/llmq/dkgsessionhandler.cpp @@ -105,7 +105,7 @@ void CDKGSessionHandler::UpdatedBlockTip(const CBlockIndex* pindexNew) { //AssertLockNotHeld(cs_main); //Indexed quorums (greater than 0) are enabled with Quorum Rotation - if (quorumIndex > 0 && !utils::IsQuorumRotationEnabled(params.type, pindexNew)) { + if (quorumIndex > 0 && !utils::IsQuorumRotationEnabled(params, pindexNew)) { return; } LOCK(cs); diff --git a/src/llmq/dkgsessionhandler.h b/src/llmq/dkgsessionhandler.h index 29aa1eb429..e099e969ed 100644 --- a/src/llmq/dkgsessionhandler.h +++ b/src/llmq/dkgsessionhandler.h @@ -109,7 +109,7 @@ private: mutable CCriticalSection cs; std::atomic stopRequested{false}; - const Consensus::LLMQParams& params; + const Consensus::LLMQParams params; CConnman& connman; const int quorumIndex; CBLSWorker& blsWorker; diff --git a/src/llmq/dkgsessionmgr.cpp b/src/llmq/dkgsessionmgr.cpp index 907b3ba80c..462195e4c3 100644 --- a/src/llmq/dkgsessionmgr.cpp +++ b/src/llmq/dkgsessionmgr.cpp @@ -197,12 +197,14 @@ void CDKGSessionManager::ProcessMessage(CNode& pfrom, const CQuorumManager& quor vRecv.Rewind(sizeof(uint256)); vRecv.Rewind(sizeof(uint8_t)); - if (!Params().HasLLMQ(llmqType)) { + const auto& llmq_params_opt = GetLLMQParams(llmqType); + if (!llmq_params_opt.has_value()) { LOCK(cs_main); LogPrintf("CDKGSessionManager -- invalid llmqType [%d]\n", ToUnderlying(llmqType)); Misbehaving(pfrom.GetId(), 100); return; } + const auto& llmq_params = llmq_params_opt.value(); int quorumIndex{-1}; @@ -233,10 +235,9 @@ void CDKGSessionManager::ProcessMessage(CNode& pfrom, const CQuorumManager& quor return; } - const Consensus::LLMQParams& llmqParams = GetLLMQParams(llmqType); - quorumIndex = pQuorumBaseBlockIndex->nHeight % llmqParams.dkgInterval; - int quorumIndexMax = utils::IsQuorumRotationEnabled(llmqType, pQuorumBaseBlockIndex) ? - llmqParams.signingActiveQuorumCount - 1 : 0; + quorumIndex = pQuorumBaseBlockIndex->nHeight % llmq_params.dkgInterval; + int quorumIndexMax = utils::IsQuorumRotationEnabled(llmq_params, pQuorumBaseBlockIndex) ? + llmq_params.signingActiveQuorumCount - 1 : 0; if (quorumIndex > quorumIndexMax) { LOCK(cs_main); diff --git a/src/llmq/instantsend.cpp b/src/llmq/instantsend.cpp index 0a08cc5942..4c96f73a7a 100644 --- a/src/llmq/instantsend.cpp +++ b/src/llmq/instantsend.cpp @@ -706,8 +706,10 @@ void CInstantSendManager::TrySignInstantSendLock(const CTransaction& tx) // compute and set cycle hash if islock is deterministic if (islock.IsDeterministic()) { + const auto& llmq_params_opt = GetLLMQParams(llmqType); + assert(llmq_params_opt); LOCK(cs_main); - const auto dkgInterval = GetLLMQParams(llmqType).dkgInterval; + const auto dkgInterval = llmq_params_opt->dkgInterval; const auto quorumHeight = ::ChainActive().Height() - (::ChainActive().Height() % dkgInterval); islock.cycleHash = ::ChainActive()[quorumHeight]->GetBlockHash(); } @@ -804,7 +806,9 @@ void CInstantSendManager::ProcessMessageInstantSendLock(const CNode& pfrom, cons // Deterministic islocks MUST use rotation based llmq auto llmqType = Params().GetConsensus().llmqTypeDIP0024InstantSend; - if (blockIndex->nHeight % GetLLMQParams(llmqType).dkgInterval != 0) { + const auto& llmq_params_opt = GetLLMQParams(llmqType); + assert(llmq_params_opt); + if (blockIndex->nHeight % llmq_params_opt->dkgInterval != 0) { WITH_LOCK(cs_main, Misbehaving(pfrom.GetId(), 100)); return; } @@ -906,10 +910,13 @@ bool CInstantSendManager::ProcessPendingInstantSendLocks(bool deterministic) //TODO Investigate if leaving this is ok auto llmqType = utils::GetInstantSendLLMQType(deterministic); - auto dkgInterval = GetLLMQParams(llmqType).dkgInterval; + const auto& llmq_params_opt = GetLLMQParams(llmqType); + assert(llmq_params_opt); + const auto& llmq_params = llmq_params_opt.value(); + auto dkgInterval = llmq_params.dkgInterval; // First check against the current active set and don't ban - auto badISLocks = ProcessPendingInstantSendLocks(llmqType, 0, pend, false); + auto badISLocks = ProcessPendingInstantSendLocks(llmq_params, 0, pend, false); if (!badISLocks.empty()) { LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- doing verification on old active set\n", __func__); @@ -922,13 +929,13 @@ bool CInstantSendManager::ProcessPendingInstantSendLocks(bool deterministic) } } // Now check against the previous active set and perform banning if this fails - ProcessPendingInstantSendLocks(llmqType, dkgInterval, pend, true); + ProcessPendingInstantSendLocks(llmq_params, dkgInterval, pend, true); } return fMoreWork; } -std::unordered_set CInstantSendManager::ProcessPendingInstantSendLocks(const Consensus::LLMQType llmqType, int signOffset, const std::unordered_map, StaticSaltedHasher>& pend, bool ban) +std::unordered_set CInstantSendManager::ProcessPendingInstantSendLocks(const Consensus::LLMQParams& llmq_params, int signOffset, const std::unordered_map, StaticSaltedHasher>& pend, bool ban) { CBLSBatchVerifier batchVerifier(false, true, 8); std::unordered_map recSigs; @@ -952,7 +959,7 @@ std::unordered_set CInstantSendManager::ProcessPend auto id = islock->GetRequestId(); // no need to verify an ISLOCK if we already have verified the recovered sig that belongs to it - if (sigman.HasRecoveredSig(llmqType, id, islock->txid)) { + if (sigman.HasRecoveredSig(llmq_params.type, id, islock->txid)) { alreadyVerified++; continue; } @@ -967,26 +974,26 @@ std::unordered_set CInstantSendManager::ProcessPend continue; } - const auto dkgInterval = GetLLMQParams(llmqType).dkgInterval; + const auto dkgInterval = llmq_params.dkgInterval; if (blockIndex->nHeight + dkgInterval < ::ChainActive().Height()) { nSignHeight = blockIndex->nHeight + dkgInterval - 1; } } - auto quorum = llmq::CSigningManager::SelectQuorumForSigning(llmqType, qman, id, nSignHeight, signOffset); + auto quorum = llmq::CSigningManager::SelectQuorumForSigning(llmq_params, qman, id, nSignHeight, signOffset); if (!quorum) { // should not happen, but if one fails to select, all others will also fail to select return {}; } - uint256 signHash = utils::BuildSignHash(llmqType, quorum->qc->quorumHash, id, islock->txid); + uint256 signHash = utils::BuildSignHash(llmq_params.type, quorum->qc->quorumHash, id, islock->txid); batchVerifier.PushMessage(nodeId, hash, signHash, islock->sig.Get(), quorum->qc->quorumPublicKey); verifyCount++; // We can reconstruct the CRecoveredSig objects from the islock and pass it to the signing manager, which // avoids unnecessary double-verification of the signature. We however only do this when verification here // turns out to be good (which is checked further down) - if (!sigman.HasRecoveredSigForId(llmqType, id)) { - recSigs.try_emplace(hash, CRecoveredSig(llmqType, quorum->qc->quorumHash, id, islock->txid, islock->sig)); + if (!sigman.HasRecoveredSigForId(llmq_params.type, id)) { + recSigs.try_emplace(hash, CRecoveredSig(llmq_params.type, quorum->qc->quorumHash, id, islock->txid, islock->sig)); } } @@ -1026,7 +1033,7 @@ std::unordered_set CInstantSendManager::ProcessPend auto it = recSigs.find(hash); if (it != recSigs.end()) { auto recSig = std::make_shared(std::move(it->second)); - if (!sigman.HasRecoveredSigForId(llmqType, recSig->getId())) { + if (!sigman.HasRecoveredSigForId(llmq_params.type, recSig->getId())) { LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, islock=%s: passing reconstructed recSig to signing mgr, peer=%d\n", __func__, islock->txid.ToString(), hash.ToString(), nodeId); sigman.PushReconstructedRecoveredSig(recSig); diff --git a/src/llmq/instantsend.h b/src/llmq/instantsend.h index ee4055b5ea..386544a960 100644 --- a/src/llmq/instantsend.h +++ b/src/llmq/instantsend.h @@ -287,7 +287,7 @@ private: bool ProcessPendingInstantSendLocks(); bool ProcessPendingInstantSendLocks(bool deterministic) LOCKS_EXCLUDED(cs_pendingLocks); - std::unordered_set ProcessPendingInstantSendLocks(const Consensus::LLMQType llmqType, + std::unordered_set ProcessPendingInstantSendLocks(const Consensus::LLMQParams& llmq_params, int signOffset, const std::unordered_map, diff --git a/src/llmq/params.h b/src/llmq/params.h index 2f0ac1f8eb..f2eb5bbb76 100644 --- a/src/llmq/params.h +++ b/src/llmq/params.h @@ -108,6 +108,11 @@ struct LLMQParams { int recoveryMembers; }; +//static_assert(std::is_trivial_v, "LLMQParams is not a trivial type"); +static_assert(std::is_trivially_copyable_v, "LLMQParams is not trivially copyable"); +//static_assert(std::is_trivially_default_constructible_v, "LLMQParams is not trivially default constructible"); +static_assert(std::is_trivially_assignable_v, "LLMQParams is not trivially assignable"); + static constexpr std::array available_llmqs = { diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 7bd215c751..3d91777e0e 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -301,7 +301,7 @@ void CQuorumManager::CheckQuorumConnections(const Consensus::LLMQParams& llmqPar auto connmanQuorumsToDelete = connman.GetMasternodeQuorums(llmqParams.type); // don't remove connections for the currently in-progress DKG round - if (utils::IsQuorumRotationEnabled(llmqParams.type, pindexNew)) { + if (utils::IsQuorumRotationEnabled(llmqParams, pindexNew)) { int cycleIndexTipHeight = pindexNew->nHeight % llmqParams.dkgInterval; int cycleQuorumBaseHeight = pindexNew->nHeight - cycleIndexTipHeight; std::stringstream ss; @@ -373,7 +373,9 @@ CQuorumPtr CQuorumManager::BuildQuorumFromCommitment(const Consensus::LLMQType l } assert(qc->quorumHash == pQuorumBaseBlockIndex->GetBlockHash()); - auto quorum = std::make_shared(llmq::GetLLMQParams(llmqType), blsWorker); + const auto& llmq_params_opt = GetLLMQParams(llmqType); + assert(llmq_params_opt.has_value()); + auto quorum = std::make_shared(llmq_params_opt.value(), blsWorker); auto members = utils::GetAllQuorumMembers(qc->llmqType, pQuorumBaseBlockIndex); quorum->Init(std::move(qc), pQuorumBaseBlockIndex, minedBlockHash, members); @@ -452,7 +454,7 @@ bool CQuorumManager::RequestQuorumData(CNode* pfrom, Consensus::LLMQType llmqTyp LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- pfrom is neither a verified masternode nor a qwatch connection\n", __func__); return false; } - if (!Params().HasLLMQ(llmqType)) { + if (!GetLLMQParams(llmqType).has_value()) { LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- Invalid llmqType: %d\n", __func__, ToUnderlying(llmqType)); return false; } @@ -525,7 +527,9 @@ std::vector CQuorumManager::ScanQuorums(Consensus::LLMQType llmqTyp } // Get the block indexes of the mined commitments to build the required quorums from - std::vector pQuorumBaseBlockIndexes{ GetLLMQParams(llmqType).useRotation ? + const auto& llmq_params_opt = GetLLMQParams(llmqType); + assert(llmq_params_opt.has_value()); + std::vector pQuorumBaseBlockIndexes{ llmq_params_opt->useRotation ? quorumBlockProcessor.GetMinedCommitmentsIndexedUntilBlock(llmqType, pIndexScanCommitments, nScanCommitments) : quorumBlockProcessor.GetMinedCommitmentsUntilBlock(llmqType, pIndexScanCommitments, nScanCommitments) }; @@ -650,7 +654,7 @@ void CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, C } } - if (!Params().HasLLMQ(request.GetLLMQType())) { + if (!GetLLMQParams(request.GetLLMQType()).has_value()) { sendQDATA(CQuorumDataRequest::Errors::QUORUM_TYPE_INVALID); return; } diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index 4ac9e4060f..5e6d12dd8c 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -158,7 +158,7 @@ class CQuorum { friend class CQuorumManager; public: - const Consensus::LLMQParams& params; + const Consensus::LLMQParams params; CFinalCommitmentPtr qc; const CBlockIndex* m_quorum_base_block_index{nullptr}; uint256 minedBlockHash; diff --git a/src/llmq/signing.cpp b/src/llmq/signing.cpp index 3089f48c08..0946f76425 100644 --- a/src/llmq/signing.cpp +++ b/src/llmq/signing.cpp @@ -607,7 +607,7 @@ bool CSigningManager::PreVerifyRecoveredSig(const CQuorumManager& quorum_manager retBan = false; auto llmqType = recoveredSig.getLlmqType(); - if (!Params().HasLLMQ(llmqType)) { + if (!GetLLMQParams(llmqType).has_value()) { retBan = true; return false; } @@ -883,7 +883,9 @@ bool CSigningManager::AsyncSignIfMember(Consensus::LLMQType llmqType, CSigShares // This gives a slight risk of not getting enough shares to recover a signature // But at least it shouldn't be possible to get conflicting recovered signatures // TODO fix this by re-signing when the next block arrives, but only when that block results in a change of the quorum list and no recovered signature has been created in the mean time - quorum = SelectQuorumForSigning(llmqType, qman, id); + const auto& llmq_params_opt = GetLLMQParams(llmqType); + assert(llmq_params_opt.has_value()); + quorum = SelectQuorumForSigning(llmq_params_opt.value(), qman, id); } else { quorum = qman.GetQuorum(llmqType, quorumHash); } @@ -980,9 +982,9 @@ bool CSigningManager::GetVoteForId(Consensus::LLMQType llmqType, const uint256& return db.GetVoteForId(llmqType, id, msgHashRet); } -CQuorumCPtr CSigningManager::SelectQuorumForSigning(Consensus::LLMQType llmqType, const CQuorumManager& quorum_manager, const uint256& selectionHash, int signHeight, int signOffset) +CQuorumCPtr CSigningManager::SelectQuorumForSigning(const Consensus::LLMQParams& llmq_params, const CQuorumManager& quorum_manager, const uint256& selectionHash, int signHeight, int signOffset) { - size_t poolSize = GetLLMQParams(llmqType).signingActiveQuorumCount; + size_t poolSize = llmq_params.signingActiveQuorumCount; CBlockIndex* pindexStart; { @@ -997,13 +999,13 @@ CQuorumCPtr CSigningManager::SelectQuorumForSigning(Consensus::LLMQType llmqType pindexStart = ::ChainActive()[startBlockHeight]; } - if (utils::IsQuorumRotationEnabled(llmqType, pindexStart)) { - auto quorums = quorum_manager.ScanQuorums(llmqType, pindexStart, poolSize); + if (utils::IsQuorumRotationEnabled(llmq_params, pindexStart)) { + auto quorums = quorum_manager.ScanQuorums(llmq_params.type, pindexStart, poolSize); if (quorums.empty()) { return nullptr; } //log2 int - int n = std::log2(GetLLMQParams(llmqType).signingActiveQuorumCount); + int n = std::log2(llmq_params.signingActiveQuorumCount); //Extract last 64 bits of selectionHash uint64_t b = selectionHash.GetUint64(3); //Take last n bits of b @@ -1022,7 +1024,7 @@ CQuorumCPtr CSigningManager::SelectQuorumForSigning(Consensus::LLMQType llmqType } return *itQuorum; } else { - auto quorums = quorum_manager.ScanQuorums(llmqType, pindexStart, poolSize); + auto quorums = quorum_manager.ScanQuorums(llmq_params.type, pindexStart, poolSize); if (quorums.empty()) { return nullptr; } @@ -1031,7 +1033,7 @@ CQuorumCPtr CSigningManager::SelectQuorumForSigning(Consensus::LLMQType llmqType scores.reserve(quorums.size()); for (const auto i : irange::range(quorums.size())) { CHashWriter h(SER_NETWORK, 0); - h << llmqType; + h << llmq_params.type; h << quorums[i]->qc->quorumHash; h << selectionHash; scores.emplace_back(h.GetHash(), i); @@ -1043,7 +1045,9 @@ CQuorumCPtr CSigningManager::SelectQuorumForSigning(Consensus::LLMQType llmqType bool CSigningManager::VerifyRecoveredSig(Consensus::LLMQType llmqType, const CQuorumManager& quorum_manager, int signedAtHeight, const uint256& id, const uint256& msgHash, const CBLSSignature& sig, const int signOffset) { - auto quorum = SelectQuorumForSigning(llmqType, quorum_manager, id, signedAtHeight, signOffset); + const auto& llmq_params_opt = GetLLMQParams(llmqType); + assert(llmq_params_opt.has_value()); + auto quorum = SelectQuorumForSigning(llmq_params_opt.value(), quorum_manager, id, signedAtHeight, signOffset); if (!quorum) { return false; } diff --git a/src/llmq/signing.h b/src/llmq/signing.h index 87ee52d7d8..1d43916691 100644 --- a/src/llmq/signing.h +++ b/src/llmq/signing.h @@ -223,7 +223,7 @@ public: bool GetVoteForId(Consensus::LLMQType llmqType, const uint256& id, uint256& msgHashRet) const; static std::vector GetActiveQuorumSet(Consensus::LLMQType llmqType, int signHeight); - static CQuorumCPtr SelectQuorumForSigning(Consensus::LLMQType llmqType, const CQuorumManager& quorum_manager, const uint256& selectionHash, int signHeight = -1 /*chain tip*/, int signOffset = SIGN_HEIGHT_OFFSET); + static CQuorumCPtr SelectQuorumForSigning(const Consensus::LLMQParams& llmq_params, const CQuorumManager& quorum_manager, const uint256& selectionHash, int signHeight = -1 /*chain tip*/, int signOffset = SIGN_HEIGHT_OFFSET); // Verifies a recovered sig that was signed while the chain tip was at signedAtTip static bool VerifyRecoveredSig(Consensus::LLMQType llmqType, const CQuorumManager& quorum_manager, int signedAtHeight, const uint256& id, const uint256& msgHash, const CBLSSignature& sig, int signOffset = SIGN_HEIGHT_OFFSET); diff --git a/src/llmq/signing_shares.cpp b/src/llmq/signing_shares.cpp index 59a1411278..d554db4601 100644 --- a/src/llmq/signing_shares.cpp +++ b/src/llmq/signing_shares.cpp @@ -97,7 +97,9 @@ std::string CBatchedSigShares::ToInvString() const static void InitSession(CSigSharesNodeState::Session& s, const uint256& signHash, CSigBase from) { - const auto& llmq_params = GetLLMQParams(from.getLlmqType()); + const auto& llmq_params_opt = GetLLMQParams(from.getLlmqType()); + assert(llmq_params_opt.has_value()); + const auto& llmq_params = llmq_params_opt.value(); s.llmqType = from.getLlmqType(); s.quorumHash = from.getQuorumHash(); @@ -297,7 +299,7 @@ void CSigSharesManager::ProcessMessage(const CNode& pfrom, const CSporkManager& bool CSigSharesManager::ProcessMessageSigSesAnn(const CNode& pfrom, const CSigSesAnn& ann) { auto llmqType = ann.getLlmqType(); - if (!Params().HasLLMQ(llmqType)) { + if (!GetLLMQParams(llmqType).has_value()) { return false; } if (ann.getSessionId() == UNINITIALIZED_SESSION_ID || ann.getQuorumHash().IsNull() || ann.getId().IsNull() || ann.getMsgHash().IsNull()) { @@ -328,7 +330,8 @@ bool CSigSharesManager::ProcessMessageSigSesAnn(const CNode& pfrom, const CSigSe bool CSigSharesManager::VerifySigSharesInv(Consensus::LLMQType llmqType, const CSigSharesInv& inv) { - return inv.inv.size() == size_t(GetLLMQParams(llmqType).size); + const auto& llmq_params_opt = GetLLMQParams(llmqType); + return llmq_params_opt.has_value() && (inv.inv.size() == size_t(llmq_params_opt->size)); } bool CSigSharesManager::ProcessMessageSigSharesInv(const CNode& pfrom, const CSigSharesInv& inv) @@ -900,7 +903,9 @@ void CSigSharesManager::CollectSigSharesToRequest(std::unordered_mapsize); } inv.inv[k.second] = true; @@ -1047,7 +1052,9 @@ void CSigSharesManager::CollectSigSharesToAnnounce(std::unordered_mapgetLlmqType()).size); + const auto& llmq_params_opt = GetLLMQParams(sigShare->getLlmqType()); + assert(llmq_params_opt.has_value()); + inv.Init(llmq_params_opt->size); } inv.inv[quorumMember] = true; session.knows.inv[quorumMember] = true; diff --git a/src/llmq/snapshot.cpp b/src/llmq/snapshot.cpp index bdf3bc3ffe..76bedfc7f3 100644 --- a/src/llmq/snapshot.cpp +++ b/src/llmq/snapshot.cpp @@ -168,8 +168,10 @@ bool BuildQuorumRotationInfo(const CGetQuorumRotationInfo& request, CQuorumRotat Consensus::LLMQType llmqType = utils::GetInstantSendLLMQType(qman, blockIndex); // Since the returned quorums are in reversed order, the most recent one is at index 0 - const Consensus::LLMQParams& llmqParams = GetLLMQParams(llmqType); - const int cycleLength = llmqParams.dkgInterval; + const auto& llmq_params_opt = GetLLMQParams(llmqType); + assert(llmq_params_opt.has_value()); + + const int cycleLength = llmq_params_opt->dkgInterval; constexpr int workDiff = 8; const CBlockIndex* hBlockIndex = blockIndex->GetAncestor(blockIndex->nHeight - (blockIndex->nHeight % cycleLength)); @@ -307,7 +309,7 @@ bool BuildQuorumRotationInfo(const CGetQuorumRotationInfo& request, CQuorumRotat } response.lastCommitmentPerIndex.push_back(*qc); - int quorumCycleStartHeight = obj.second->nHeight - (obj.second->nHeight % llmqParams.dkgInterval); + int quorumCycleStartHeight = obj.second->nHeight - (obj.second->nHeight % llmq_params_opt->dkgInterval); snapshotHeightsNeeded.insert(quorumCycleStartHeight - cycleLength); snapshotHeightsNeeded.insert(quorumCycleStartHeight - 2 * cycleLength); snapshotHeightsNeeded.insert(quorumCycleStartHeight - 3 * cycleLength); diff --git a/src/llmq/utils.cpp b/src/llmq/utils.cpp index 5e5c6417c2..ce0fba766c 100644 --- a/src/llmq/utils.cpp +++ b/src/llmq/utils.cpp @@ -52,7 +52,7 @@ static bool IsInstantSendLLMQTypeShared(); void PreComputeQuorumMembers(const CBlockIndex* pQuorumBaseBlockIndex, bool reset_cache) { for (const Consensus::LLMQParams& params : GetEnabledQuorumParams(pQuorumBaseBlockIndex->pprev)) { - if (IsQuorumRotationEnabled(params.type, pQuorumBaseBlockIndex) && (pQuorumBaseBlockIndex->nHeight % params.dkgInterval == 0)) { + if (IsQuorumRotationEnabled(params, pQuorumBaseBlockIndex) && (pQuorumBaseBlockIndex->nHeight % params.dkgInterval == 0)) { GetAllQuorumMembers(params.type, pQuorumBaseBlockIndex, reset_cache); } } @@ -80,7 +80,11 @@ std::vector GetAllQuorumMembers(Consensus::LLMQType llmqTy } } - if (IsQuorumRotationEnabled(llmqType, pQuorumBaseBlockIndex)) { + const auto& llmq_params_opt = GetLLMQParams(llmqType); + assert(llmq_params_opt.has_value()); + const auto& llmq_params = llmq_params_opt.value(); + + if (IsQuorumRotationEnabled(llmq_params, pQuorumBaseBlockIndex)) { if (LOCK(cs_indexed_members); mapIndexedQuorumMembers.empty()) { InitQuorumsCache(mapIndexedQuorumMembers); } @@ -93,9 +97,8 @@ std::vector GetAllQuorumMembers(Consensus::LLMQType llmqTy * Quorum Q with quorumIndex is created at height CycleQuorumBaseBlock + quorumIndex */ - const Consensus::LLMQParams& llmqParams = GetLLMQParams(llmqType); - int quorumIndex = pQuorumBaseBlockIndex->nHeight % llmqParams.dkgInterval; - if (quorumIndex >= llmqParams.signingActiveQuorumCount) { + int quorumIndex = pQuorumBaseBlockIndex->nHeight % llmq_params.dkgInterval; + if (quorumIndex >= llmq_params.signingActiveQuorumCount) { return {}; } int cycleQuorumBaseHeight = pQuorumBaseBlockIndex->nHeight - quorumIndex; @@ -114,7 +117,7 @@ std::vector GetAllQuorumMembers(Consensus::LLMQType llmqTy return quorumMembers; } - auto q = ComputeQuorumMembersByQuarterRotation(llmqParams, pCycleQuorumBaseBlockIndex); + auto q = ComputeQuorumMembersByQuarterRotation(llmq_params, pCycleQuorumBaseBlockIndex); LOCK(cs_indexed_members); for (const size_t i : irange::range(q.size())) { mapIndexedQuorumMembers[llmqType].insert(std::make_pair(pCycleQuorumBaseBlockIndex->GetBlockHash(), i), q[i]); @@ -135,7 +138,9 @@ std::vector ComputeQuorumMembers(Consensus::LLMQType llmqT auto allMns = deterministicMNManager->GetListForBlock(pQuorumBaseBlockIndex); auto modifier = ::SerializeHash(std::make_pair(llmqType, pQuorumBaseBlockIndex->GetBlockHash())); bool HPMNOnly = (Params().GetConsensus().llmqTypePlatform == llmqType) && IsV19Active(pQuorumBaseBlockIndex); - return allMns.CalculateQuorum(GetLLMQParams(llmqType).size, modifier, HPMNOnly); + const auto& llmq_params_opt = GetLLMQParams(llmqType); + assert(llmq_params_opt.has_value()); + return allMns.CalculateQuorum(llmq_params_opt->size, modifier, HPMNOnly); } std::vector> ComputeQuorumMembersByQuarterRotation(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pCycleQuorumBaseBlockIndex) @@ -608,12 +613,10 @@ bool IsQuorumPoseEnabled(Consensus::LLMQType llmqType) return EvalSpork(llmqType, sporkManager->GetSporkValue(SPORK_23_QUORUM_POSE)); } -bool IsQuorumRotationEnabled(Consensus::LLMQType llmqType, const CBlockIndex* pindex) +bool IsQuorumRotationEnabled(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pindex) { assert(pindex); - const auto& llmqParams = GetLLMQParams(llmqType); - if (!llmqParams.useRotation) { return false; } @@ -902,7 +905,9 @@ bool IsQuorumActive(Consensus::LLMQType llmqType, const CQuorumManager& qman, co // sig shares and recovered sigs are only accepted from recent/active quorums // we allow one more active quorum as specified in consensus, as otherwise there is a small window where things could // fail while we are on the brink of a new quorum - auto quorums = qman.ScanQuorums(llmqType, GetLLMQParams(llmqType).keepOldConnections); + const auto& llmq_params_opt = GetLLMQParams(llmqType); + assert(llmq_params_opt.has_value()); + auto quorums = qman.ScanQuorums(llmqType, llmq_params_opt->keepOldConnections); return ranges::any_of(quorums, [&quorumHash](const auto& q){ return q->qc->quorumHash == quorumHash; }); } @@ -1064,7 +1069,7 @@ template void InitQuorumsCache GetLLMQParams(Consensus::LLMQType llmqType) { return Params().GetLLMQ(llmqType); } diff --git a/src/llmq/utils.h b/src/llmq/utils.h index a29a35f62e..289d6b4bc3 100644 --- a/src/llmq/utils.h +++ b/src/llmq/utils.h @@ -79,7 +79,7 @@ bool IsQuorumTypeEnabledInternal(Consensus::LLMQType llmqType, const CQuorumMana std::vector GetEnabledQuorumTypes(const CBlockIndex* pindex); std::vector> GetEnabledQuorumParams(const CBlockIndex* pindex); -bool IsQuorumRotationEnabled(Consensus::LLMQType llmqType, const CBlockIndex* pindex); +bool IsQuorumRotationEnabled(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pindex); Consensus::LLMQType GetInstantSendLLMQType(const CQuorumManager& qman, const CBlockIndex* pindex); Consensus::LLMQType GetInstantSendLLMQType(bool deterministic); bool IsDIP0024Active(const CBlockIndex* pindex); @@ -130,7 +130,7 @@ void InitQuorumsCache(CacheType& cache); } // namespace utils -const Consensus::LLMQParams& GetLLMQParams(Consensus::LLMQType llmqType); +[[ nodiscard ]] const std::optional GetLLMQParams(Consensus::LLMQType llmqType); } // namespace llmq diff --git a/src/rpc/quorums.cpp b/src/rpc/quorums.cpp index 3ea90cb4b5..a0a0839e0d 100644 --- a/src/rpc/quorums.cpp +++ b/src/rpc/quorums.cpp @@ -70,15 +70,16 @@ static UniValue quorum_list(const JSONRPCRequest& request) CBlockIndex* pindexTip = WITH_LOCK(cs_main, return ::ChainActive().Tip()); for (const auto& type : llmq::utils::GetEnabledQuorumTypes(pindexTip)) { - const auto& llmq_params = llmq::GetLLMQParams(type); + const auto& llmq_params_opt = llmq::GetLLMQParams(type); + CHECK_NONFATAL(llmq_params_opt.has_value()); UniValue v(UniValue::VARR); - auto quorums = llmq_ctx.qman->ScanQuorums(type, pindexTip, count > -1 ? count : llmq_params.signingActiveQuorumCount); + auto quorums = llmq_ctx.qman->ScanQuorums(type, pindexTip, count > -1 ? count : llmq_params_opt->signingActiveQuorumCount); for (const auto& q : quorums) { v.push_back(q->qc->quorumHash.ToString()); } - ret.pushKV(std::string(llmq_params.name), v); + ret.pushKV(std::string(llmq_params_opt->name), v); } return ret; @@ -135,7 +136,9 @@ static UniValue quorum_list_extended(const JSONRPCRequest& request) CBlockIndex* pblockindex = nHeight != -1 ? WITH_LOCK(cs_main, return ::ChainActive()[nHeight]) : WITH_LOCK(cs_main, return ::ChainActive().Tip()); for (const auto& type : llmq::utils::GetEnabledQuorumTypes(pblockindex)) { - const auto& llmq_params = llmq::GetLLMQParams(type); + const auto& llmq_params_opt = llmq::GetLLMQParams(type); + CHECK_NONFATAL(llmq_params_opt.has_value()); + const auto& llmq_params = llmq_params_opt.value(); UniValue v(UniValue::VARR); auto quorums = llmq_ctx.qman->ScanQuorums(type, pblockindex, llmq_params.signingActiveQuorumCount); @@ -233,7 +236,7 @@ static UniValue quorum_info(const JSONRPCRequest& request) quorum_info_help(request); Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[0], "llmqType"); - if (!Params().HasLLMQ(llmqType)) { + if (!llmq::GetLLMQParams(llmqType).has_value()) { throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid LLMQ type"); } @@ -293,8 +296,10 @@ static UniValue quorum_dkgstatus(const JSONRPCRequest& request) UniValue minableCommitments(UniValue::VARR); UniValue quorumArrConnections(UniValue::VARR); for (const auto& type : llmq::utils::GetEnabledQuorumTypes(pindexTip)) { - const auto& llmq_params = llmq::GetLLMQParams(type); - bool rotation_enabled = llmq::utils::IsQuorumRotationEnabled(type, pindexTip); + const auto& llmq_params_opt = llmq::GetLLMQParams(type); + CHECK_NONFATAL(llmq_params_opt.has_value()); + const auto& llmq_params = llmq_params_opt.value(); + bool rotation_enabled = llmq::utils::IsQuorumRotationEnabled(llmq_params, pindexTip); int quorums_num = rotation_enabled ? llmq_params.signingActiveQuorumCount : 1; for (const int quorumIndex : irange::range(quorums_num)) { @@ -397,12 +402,13 @@ static UniValue quorum_memberof(const JSONRPCRequest& request) UniValue result(UniValue::VARR); for (const auto& type : llmq::utils::GetEnabledQuorumTypes(pindexTip)) { - const auto& llmq_params = llmq::GetLLMQParams(type); - size_t count = llmq_params.signingActiveQuorumCount; + const auto& llmq_params_opt = llmq::GetLLMQParams(type); + CHECK_NONFATAL(llmq_params_opt.has_value()); + size_t count = llmq_params_opt->signingActiveQuorumCount; if (scanQuorumsCount != -1) { count = (size_t)scanQuorumsCount; } - auto quorums = llmq_ctx.qman->ScanQuorums(llmq_params.type, count); + auto quorums = llmq_ctx.qman->ScanQuorums(llmq_params_opt->type, count); for (auto& quorum : quorums) { if (quorum->IsMember(dmn->proTxHash)) { auto json = BuildQuorumInfo(quorum, false, false); @@ -519,7 +525,8 @@ static UniValue quorum_sigs_cmd(const JSONRPCRequest& request) LLMQContext& llmq_ctx = EnsureLLMQContext(request.context); Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[0], "llmqType"); - if (!Params().HasLLMQ(llmqType)) { + const auto& llmq_params_opt = llmq::GetLLMQParams(llmqType); + if (!llmq_params_opt.has_value()) { throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid LLMQ type"); } @@ -541,7 +548,7 @@ static UniValue quorum_sigs_cmd(const JSONRPCRequest& request) llmq::CQuorumCPtr pQuorum; if (quorumHash.IsNull()) { - pQuorum = llmq_ctx.sigman->SelectQuorumForSigning(llmqType, *llmq_ctx.qman, id); + pQuorum = llmq_ctx.sigman->SelectQuorumForSigning(llmq_params_opt.value(), *llmq_ctx.qman, id); } else { pQuorum = llmq_ctx.qman->GetQuorum(llmqType, quorumHash); } @@ -579,7 +586,7 @@ static UniValue quorum_sigs_cmd(const JSONRPCRequest& request) signHeight = ParseInt32V(request.params[5], "signHeight"); } // First check against the current active set, if it fails check against the last active set - int signOffset{llmq::GetLLMQParams(llmqType).dkgInterval}; + int signOffset{llmq_params_opt->dkgInterval}; return llmq_ctx.sigman->VerifyRecoveredSig(llmqType, *llmq_ctx.qman, signHeight, id, msgHash, sig, 0) || llmq_ctx.sigman->VerifyRecoveredSig(llmqType, *llmq_ctx.qman, signHeight, id, msgHash, sig, signOffset); } else { @@ -630,7 +637,8 @@ static UniValue quorum_selectquorum(const JSONRPCRequest& request) quorum_selectquorum_help(request); Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[0], "llmqType"); - if (!Params().HasLLMQ(llmqType)) { + const auto& llmq_params_opt = llmq::GetLLMQParams(llmqType); + if (!llmq_params_opt.has_value()) { throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid LLMQ type"); } @@ -639,7 +647,7 @@ static UniValue quorum_selectquorum(const JSONRPCRequest& request) UniValue ret(UniValue::VOBJ); LLMQContext& llmq_ctx = EnsureLLMQContext(request.context); - auto quorum = llmq_ctx.sigman->SelectQuorumForSigning(llmqType, *llmq_ctx.qman, id); + auto quorum = llmq_ctx.sigman->SelectQuorumForSigning(llmq_params_opt.value(), *llmq_ctx.qman, id); if (!quorum) { throw JSONRPCError(RPC_MISC_ERROR, "no quorums active"); } @@ -955,7 +963,9 @@ static UniValue verifyislock(const JSONRPCRequest& request) auto llmqType = llmq::utils::GetInstantSendLLMQType(*llmq_ctx.qman, pBlockIndex); // First check against the current active set, if it fails check against the last active set - int signOffset{llmq::GetLLMQParams(llmqType).dkgInterval}; + const auto& llmq_params_opt = llmq::GetLLMQParams(llmqType); + CHECK_NONFATAL(llmq_params_opt.has_value()); + int signOffset{llmq_params_opt->dkgInterval}; return llmq_ctx.sigman->VerifyRecoveredSig(llmqType, *llmq_ctx.qman, signHeight, id, txid, sig, 0) || llmq_ctx.sigman->VerifyRecoveredSig(llmqType, *llmq_ctx.qman, signHeight, id, txid, sig, signOffset); } From cdb9d68720d24502654bb52c7ea5b429101ab1dc Mon Sep 17 00:00:00 2001 From: pasta Date: Mon, 13 Mar 2023 11:26:25 -0500 Subject: [PATCH 25/63] chore: bump to rc.6 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 930ef433b9..3def30d01b 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 19) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 5) +define(_CLIENT_VERSION_RC, 6) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2023) define(_COPYRIGHT_HOLDERS,[The %s developers]) From 79dbb0d7399518706a90cb5dbe39b0ce87d0d3d6 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Mon, 20 Mar 2023 17:39:44 +0200 Subject: [PATCH 26/63] feat: isdlock support without quorum rotation (regtest only) (#5259) --- src/chainparams.cpp | 66 ++++++++++++++++++++++++++++++++++++++ src/llmq/dkgsessionmgr.cpp | 2 +- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 6ba180563d..f2ed956850 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -1045,6 +1046,8 @@ public: UpdateLLMQTestParametersFromArgs(args, Consensus::LLMQType::LLMQ_TEST); UpdateLLMQTestParametersFromArgs(args, Consensus::LLMQType::LLMQ_TEST_INSTANTSEND); + UpdateLLMQInstantSendFromArgs(args); + UpdateLLMQInstantSendDIP0024FromArgs(args); } /** @@ -1111,7 +1114,26 @@ public: params->threshold = threshold; params->dkgBadVotesThreshold = threshold; } + + /** + * Allows modifying the LLMQ type for InstantSend. + */ + void UpdateLLMQInstantSend(Consensus::LLMQType llmqType) + { + consensus.llmqTypeInstantSend = llmqType; + } + + /** + * Allows modifying the LLMQ type for InstantSend (DIP0024). + */ + void UpdateLLMQDIP0024InstantSend(Consensus::LLMQType llmqType) + { + consensus.llmqTypeDIP0024InstantSend = llmqType; + } + void UpdateLLMQTestParametersFromArgs(const ArgsManager& args, const Consensus::LLMQType llmqType); + void UpdateLLMQInstantSendFromArgs(const ArgsManager& args); + void UpdateLLMQInstantSendDIP0024FromArgs(const ArgsManager& args); }; void CRegTestParams::UpdateVersionBitsParametersFromArgs(const ArgsManager& args) @@ -1253,6 +1275,50 @@ void CRegTestParams::UpdateLLMQTestParametersFromArgs(const ArgsManager& args, c UpdateLLMQTestParameters(size, threshold, llmqType); } +void CRegTestParams::UpdateLLMQInstantSendFromArgs(const ArgsManager& args) +{ + if (!args.IsArgSet("-llmqinstantsend")) return; + + const auto& llmq_params_opt = GetLLMQ(consensus.llmqTypeInstantSend); + assert(llmq_params_opt.has_value()); + + std::string strLLMQType = gArgs.GetArg("-llmqinstantsend", std::string(llmq_params_opt->name)); + + Consensus::LLMQType llmqType = Consensus::LLMQType::LLMQ_NONE; + for (const auto& params : consensus.llmqs) { + if (params.name == strLLMQType) { + llmqType = params.type; + } + } + if (llmqType == Consensus::LLMQType::LLMQ_NONE) { + throw std::runtime_error("Invalid LLMQ type specified for -llmqinstantsend."); + } + LogPrintf("Setting llmqinstantsend to size=%ld\n", ToUnderlying(llmqType)); + UpdateLLMQInstantSend(llmqType); +} + +void CRegTestParams::UpdateLLMQInstantSendDIP0024FromArgs(const ArgsManager& args) +{ + if (!args.IsArgSet("-llmqinstantsenddip0024")) return; + + const auto& llmq_params_opt = GetLLMQ(consensus.llmqTypeDIP0024InstantSend); + assert(llmq_params_opt.has_value()); + + std::string strLLMQType = gArgs.GetArg("-llmqinstantsenddip0024", std::string(llmq_params_opt->name)); + + Consensus::LLMQType llmqType = Consensus::LLMQType::LLMQ_NONE; + for (const auto& params : consensus.llmqs) { + if (params.name == strLLMQType) { + llmqType = params.type; + } + } + if (llmqType == Consensus::LLMQType::LLMQ_NONE) { + throw std::runtime_error("Invalid LLMQ type specified for -llmqinstantsenddip0024."); + } + LogPrintf("Setting llmqinstantsenddip0024 to size=%ld\n", ToUnderlying(llmqType)); + UpdateLLMQDIP0024InstantSend(llmqType); +} + void CDevNetParams::UpdateDevnetSubsidyAndDiffParametersFromArgs(const ArgsManager& args) { if (!args.IsArgSet("-minimumdifficultyblocks") && !args.IsArgSet("-highsubsidyblocks") && !args.IsArgSet("-highsubsidyfactor")) return; diff --git a/src/llmq/dkgsessionmgr.cpp b/src/llmq/dkgsessionmgr.cpp index 462195e4c3..28c0d21146 100644 --- a/src/llmq/dkgsessionmgr.cpp +++ b/src/llmq/dkgsessionmgr.cpp @@ -35,7 +35,7 @@ CDKGSessionManager::CDKGSessionManager(CConnman& _connman, CBLSWorker& _blsWorke const Consensus::Params& consensus_params = Params().GetConsensus(); for (const auto& params : consensus_params.llmqs) { - auto session_count = (params.type == consensus_params.llmqTypeDIP0024InstantSend) ? params.signingActiveQuorumCount : 1; + auto session_count = (params.useRotation) ? params.signingActiveQuorumCount : 1; for (const auto i : irange::range(session_count)) { dkgSessionHandlers.emplace(std::piecewise_construct, std::forward_as_tuple(params.type, i), From bbab474c92d9d4c55631c107659d83e8121ae0d7 Mon Sep 17 00:00:00 2001 From: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> Date: Fri, 17 Mar 2023 10:40:05 -0500 Subject: [PATCH 27/63] Merge pull request #5258 from kittywhiskers/update_dashbls depends: update 'src/dashbls' to dashpay/bls-signatures@9329803 as c1992c1 --- src/dashbls/.github/workflows/build-binds.yml | 9 +- src/dashbls/.github/workflows/build-test.yaml | 6 +- .../.github/workflows/build-wheels.yml | 33 +- src/dashbls/depends/catch2/CMakeLists.txt | 6 +- src/dashbls/include/dashbls/bls.hpp | 2 +- src/dashbls/js-bindings/CMakeLists.txt | 12 +- src/dashbls/js-bindings/blsjs.d.ts | 74 +- .../js-bindings/bundle_wasm_for_web.js | 37 + src/dashbls/js-bindings/jsbindings.cpp | 78 +- src/dashbls/js-bindings/package-lock.json | 4476 ++++++++++++++++- src/dashbls/js-bindings/package.json | 19 +- .../js-bindings/tests/PrivateKey.spec.js | 20 +- .../js-bindings/tests/PublicKey.spec.js | 18 +- .../js-bindings/tests/Signature.spec.js | 36 +- src/dashbls/js-bindings/tests/test.js | 222 +- src/dashbls/js-bindings/tests/typings.spec.ts | 14 +- src/dashbls/js_build_docker.sh | 18 + src/dashbls/python-bindings/CMakeLists.txt | 2 +- src/dashbls/setup.py | 4 +- src/dashbls/src/bls.cpp | 6 +- src/dashbls/src/elements.cpp | 8 +- 21 files changed, 4653 insertions(+), 447 deletions(-) create mode 100644 src/dashbls/js-bindings/bundle_wasm_for_web.js create mode 100755 src/dashbls/js_build_docker.sh diff --git a/src/dashbls/.github/workflows/build-binds.yml b/src/dashbls/.github/workflows/build-binds.yml index fa33c6805f..92e0f04ec2 100644 --- a/src/dashbls/.github/workflows/build-binds.yml +++ b/src/dashbls/.github/workflows/build-binds.yml @@ -24,14 +24,13 @@ jobs: matrix: os: [macos-latest, ubuntu-latest] golang: [ '1.17' ] - python: ['3.7', '3.8', '3.9', '3.10'] + python: ['3.7', '3.8', '3.9', '3.10', '3.11'] steps: - name: Checkout code uses: actions/checkout@v3 - - uses: actions/setup-python@v2 - name: Install Python + - uses: chia-network/actions/setup-python@main with: python-version: ${{ matrix.python }} @@ -60,9 +59,7 @@ jobs: if: startsWith(matrix.os, 'ubuntu') run: | sudo apt-get update - sudo apt-get install -qq --yes snap libgmp-dev - sudo apt-get remove --purge cmake -y - sudo snap install cmake --classic + sudo apt-get install -qq --yes valgrind libgmp-dev cmake hash -r cmake --version diff --git a/src/dashbls/.github/workflows/build-test.yaml b/src/dashbls/.github/workflows/build-test.yaml index 0568888ed0..67ea03f8a4 100644 --- a/src/dashbls/.github/workflows/build-test.yaml +++ b/src/dashbls/.github/workflows/build-test.yaml @@ -38,9 +38,7 @@ jobs: if: startsWith(matrix.os, 'ubuntu') run: | sudo apt-get update - sudo apt-get install -qq --yes valgrind snap libgmp-dev libsodium-dev - sudo apt-get remove --purge cmake -y - sudo snap install cmake --classic + sudo apt-get install -qq --yes valgrind libgmp-dev cmake hash -r cmake --version @@ -49,7 +47,7 @@ jobs: run: | ls -l export MACOSX_DEPLOYMENT_TARGET=10.14 - brew install autoconf automake gmp + brew install autoconf automake gmp pkg-config - name: Build library using CMake if: startsWith(matrix.builder, 'cmake') diff --git a/src/dashbls/.github/workflows/build-wheels.yml b/src/dashbls/.github/workflows/build-wheels.yml index d5c9680ca5..6953beebc5 100644 --- a/src/dashbls/.github/workflows/build-wheels.yml +++ b/src/dashbls/.github/workflows/build-wheels.yml @@ -43,16 +43,34 @@ jobs: python: - major-dot-minor: '3.7' cibw-build: 'cp37-*' + manylinux: + arch: manylinux2014 + intel: manylinux2010 matrix: '3.7' - major-dot-minor: '3.8' cibw-build: 'cp38-*' + manylinux: + arch: manylinux2014 + intel: manylinux2010 matrix: '3.8' - major-dot-minor: '3.9' cibw-build: 'cp39-*' + manylinux: + arch: manylinux2014 + intel: manylinux2010 matrix: '3.9' - major-dot-minor: '3.10' cibw-build: 'cp310-*' + manylinux: + arch: manylinux2014 + intel: manylinux2010 matrix: '3.10' + - major-dot-minor: '3.11' + cibw-build: 'cp311-*' + manylinux: + arch: manylinux2014 + intel: manylinux2014 + matrix: '3.11' arch: - name: ARM matrix: arm @@ -114,25 +132,24 @@ jobs: - name: Install pipx run: | pip install pipx + - name: Build and test - uses: pypa/cibuildwheel@v2.7.0 - with: - output-dir: dist env: + CIBW_PRERELEASE_PYTHONS: True CIBW_BUILD_VERBOSITY_MACOS: 0 CIBW_BUILD_VERBOSITY_LINUX: 0 CIBW_BUILD_VERBOSITY_WINDOWS: 0 CIBW_BUILD: ${{ matrix.python.cibw-build }} CIBW_SKIP: '*-manylinux_i686 *-win32 *-musllinux_*' - CIBW_MANYLINUX_AARCH64_IMAGE: manylinux2014 - CIBW_MANYLINUX_X86_64_IMAGE: manylinux2010 - CIBW_ENVIRONMENT_LINUX: "PATH=/project/cmake-3.17.3-Linux-`uname -m`/bin:$PATH" + CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.python.manylinux['arm'] }} + CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.python.manylinux['intel'] }} + CIBW_ENVIRONMENT_LINUX: "PATH=/project/cmake-3.14.3-Linux-`uname -m`/bin:$PATH" CIBW_BEFORE_ALL_LINUX: > yum -y install epel-release && echo "epel-release installed" && yum -y install lzip && echo "lzip installed" - && curl -L https://github.com/Kitware/CMake/releases/download/v3.17.3/cmake-3.17.3-Linux-`uname -m`.sh > cmake.sh + && curl -L https://github.com/Kitware/CMake/releases/download/v3.14.3/cmake-3.14.3-Linux-`uname -m`.sh > cmake.sh && yes | sh cmake.sh | cat && rm -f /usr/bin/cmake && curl -L https://gmplib.org/download/gmp/gmp-6.2.1.tar.lz | tar x --lzip @@ -176,6 +193,8 @@ jobs: && cp {wheel} {dest_dir} CIBW_TEST_REQUIRES: pytest CIBW_TEST_COMMAND: py.test -v {project}/python-bindings/test.py + run: + pipx run --spec='cibuildwheel==2.9.0' cibuildwheel --output-dir dist 2>&1 - name: Upload artifacts uses: actions/upload-artifact@v3 diff --git a/src/dashbls/depends/catch2/CMakeLists.txt b/src/dashbls/depends/catch2/CMakeLists.txt index 8fdfcf0189..8c26a03af5 100644 --- a/src/dashbls/depends/catch2/CMakeLists.txt +++ b/src/dashbls/depends/catch2/CMakeLists.txt @@ -8,7 +8,6 @@ project( LANGUAGES CXX ) - set( ${PROJECT_NAME}_HEADERS catch2/catch.hpp @@ -22,6 +21,11 @@ list( add_library( ${PROJECT_NAME} INTERFACE +) + +target_sources( + ${PROJECT_NAME} + INTERFACE "${${PROJECT_NAME}_HEADERS}" ) diff --git a/src/dashbls/include/dashbls/bls.hpp b/src/dashbls/include/dashbls/bls.hpp index 89ecf6af6c..cd6922a58c 100644 --- a/src/dashbls/include/dashbls/bls.hpp +++ b/src/dashbls/include/dashbls/bls.hpp @@ -41,7 +41,7 @@ class BLS { static void SetSecureAllocator(Util::SecureAllocCallback allocCb, Util::SecureFreeCallback freeCb); - static void CheckRelicErrors(); + static void CheckRelicErrors(bool should_throw = true); }; } // end namespace bls diff --git a/src/dashbls/js-bindings/CMakeLists.txt b/src/dashbls/js-bindings/CMakeLists.txt index 3087eeddd1..55de66444a 100644 --- a/src/dashbls/js-bindings/CMakeLists.txt +++ b/src/dashbls/js-bindings/CMakeLists.txt @@ -13,24 +13,26 @@ include_directories( file(GLOB_RECURSE WRAP_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/wrappers/*.h) file(GLOB_RECURSE WRAP_SRC ${CMAKE_CURRENT_SOURCE_DIR}/wrappers/*.cpp) -add_executable(blsjs ${CMAKE_CURRENT_SOURCE_DIR}/jsbindings.cpp +add_executable(blsjstmp ${CMAKE_CURRENT_SOURCE_DIR}/jsbindings.cpp ${WRAP_HEADERS} ${WRAP_SRC} ${CMAKE_CURRENT_SOURCE_DIR}/helpers.h ${CMAKE_CURRENT_SOURCE_DIR}/helpers.cpp ) add_custom_target(install_npm_dependencies npm ci) -add_dependencies(blsjs install_npm_dependencies) -target_link_libraries(blsjs PRIVATE dashbls) +add_dependencies(blsjstmp install_npm_dependencies) +target_link_libraries(blsjstmp PRIVATE dashbls) # Copy necessary files for the npm package configure_file(${CMAKE_CURRENT_SOURCE_DIR}/package.json package.json COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/package-lock.json package-lock.json COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/blsjs.d.ts blsjs.d.ts COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README.md README.md COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/bundle_wasm_for_web.js bundle_wasm_for_web.js COPYONLY) # Copy test files -file(GLOB JS_BINDINGS_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/tests/ ${CMAKE_CURRENT_SOURCE_DIR}/tests/*.js ${CMAKE_CURRENT_SOURCE_DIR}/tests/*.ts) +file(GLOB JS_BINDINGS_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/tests/ ${CMAKE_CURRENT_SOURCE_DIR}/tests/*) foreach(file ${JS_BINDINGS_TESTS}) message(FILE ${file}) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tests/${file} tests/${file} COPYONLY) endforeach() -set_target_properties(blsjs PROPERTIES LINK_FLAGS "--bind -Oz --closure 1 -s MODULARIZE=1") +set_target_properties(blsjstmp PROPERTIES LINK_FLAGS "--bind -Oz --closure 1 -s MODULARIZE=1 -s NODEJS_CATCH_EXIT=1 -s NODEJS_CATCH_REJECTION=1") +add_custom_command(TARGET blsjstmp POST_BUILD COMMAND npm run build:web) diff --git a/src/dashbls/js-bindings/blsjs.d.ts b/src/dashbls/js-bindings/blsjs.d.ts index 22e69d8e0f..4cd30bc621 100644 --- a/src/dashbls/js-bindings/blsjs.d.ts +++ b/src/dashbls/js-bindings/blsjs.d.ts @@ -1,95 +1,95 @@ export declare class AugSchemeMPL { - static sk_to_g1(sk: PrivateKey): G1Element; - static key_gen(msg: Uint8Array): PrivateKey; + static skToG1(sk: PrivateKey): G1Element; + static keyGen(msg: Uint8Array): PrivateKey; static sign(sk: PrivateKey, msg: Uint8Array): G2Element; - static sign_prepend(sk: PrivateKey, msg: Uint8Array, prependPk: G1Element): G2Element; + static signPrepend(sk: PrivateKey, msg: Uint8Array, prependPk: G1Element): G2Element; static verify(pk: G1Element, msg: Uint8Array, sig: G2Element): boolean; static aggregate(g2Elements: G2Element[]): G2Element; - static aggregate_verify(pks: G1Element[], msgs: Uint8Array[], sig: G2Element): boolean; - static derive_child_sk(sk: PrivateKey, index: number): PrivateKey; - static derive_child_sk_unhardened(sk: PrivateKey, index: number): PrivateKey; - static derive_child_pk_unhardened(pk: G1Element, index: number): G1Element; + static aggregateVerify(pks: G1Element[], msgs: Uint8Array[], sig: G2Element): boolean; + static deriveChildSk(sk: PrivateKey, index: number): PrivateKey; + static deriveChildSkUnhardened(sk: PrivateKey, index: number): PrivateKey; + static deriveChildPkUnhardened(pk: G1Element, index: number): G1Element; } export declare class BasicSchemeMPL { - static sk_to_g1(sk: PrivateKey): G1Element; - static key_gen(msg: Uint8Array): PrivateKey; + static skToG1(sk: PrivateKey): G1Element; + static keyGen(msg: Uint8Array): PrivateKey; static sign(sk: PrivateKey, msg: Uint8Array): G2Element; static verify(pk: G1Element, msg: Uint8Array, sig: G2Element): boolean; static aggregate(g2Elements: G2Element[]): G2Element; - static aggregate_verify(pks: G1Element[], msgs: Uint8Array[], sig: G2Element): boolean; - static derive_child_sk(sk: PrivateKey, index: number): PrivateKey; - static derive_child_sk_unhardened(sk: PrivateKey, index: number): PrivateKey; - static derive_child_pk_unhardened(pk: G1Element, index: number): G1Element; + static aggregateVerify(pks: G1Element[], msgs: Uint8Array[], sig: G2Element): boolean; + static deriveChildSk(sk: PrivateKey, index: number): PrivateKey; + static deriveChildSkUnhardened(sk: PrivateKey, index: number): PrivateKey; + static deriveChildPkUnhardened(pk: G1Element, index: number): G1Element; } export declare class PopSchemeMPL { - static sk_to_g1(sk: PrivateKey): G1Element; - static key_gen(msg: Uint8Array): PrivateKey; + static skToG1(sk: PrivateKey): G1Element; + static keyGen(msg: Uint8Array): PrivateKey; static sign(sk: PrivateKey, msg: Uint8Array): G2Element; static verify(pk: G1Element, msg: Uint8Array, sig: G2Element): boolean; static aggregate(g2Elements: G2Element[]): G2Element; - static aggregate_verify(pks: G1Element[], msgs: Uint8Array[], sig: G2Element): boolean; - static derive_child_sk(sk: PrivateKey, index: number): PrivateKey; - static derive_child_sk_unhardened(sk: PrivateKey, index: number): PrivateKey; - static derive_child_pk_unhardened(pk: G1Element, index: number): G1Element; - static pop_prove(sk: PrivateKey): G2Element; - static pop_verify(pk: G1Element, signatureProof: G2Element): boolean; - static fast_aggregate_verify(pks: G1Element[], msg: Uint8Array, sig: G2Element): boolean; + static aggregateVerify(pks: G1Element[], msgs: Uint8Array[], sig: G2Element): boolean; + static deriveChildSk(sk: PrivateKey, index: number): PrivateKey; + static deriveChildSkUnhardened(sk: PrivateKey, index: number): PrivateKey; + static deriveChildPkUnhardened(pk: G1Element, index: number): G1Element; + static popProve(sk: PrivateKey): G2Element; + static popVerify(pk: G1Element, signatureProof: G2Element): boolean; + static fastAggregateVerify(pks: G1Element[], msg: Uint8Array, sig: G2Element): boolean; } export declare class G1Element { static SIZE: number; - static from_bytes(bytes: Uint8Array): G1Element; + static fromBytes(bytes: Uint8Array): G1Element; static generator(): G2Element; serialize(): Uint8Array; negate(): G1Element; deepcopy(): G1Element; - get_fingerprint(): number; + getFingerprint(): number; add(el: G1Element): G1Element; mul(bn: Bignum): G1Element; - equal_to(el: G1Element): boolean; + equalTo(el: G1Element): boolean; delete(): void; } export declare class G2Element { static SIZE: number; - static from_bytes(bytes: Uint8Array): G2Element; - static from_g2(sk: G2Element): G2Element; - static aggregate_sigs(sigs: G2Element[]): G2Element; + static fromBytes(bytes: Uint8Array): G2Element; + static fromG2(sk: G2Element): G2Element; + static aggregateSigs(sigs: G2Element[]): G2Element; static generator(): G2Element; serialize(): Uint8Array; negate(): G2Element; deepcopy(): G2Element; add(el: G2Element): G2Element; mul(bn: Bignum): G2Element; - equal_to(el: G2Element): boolean; + equalTo(el: G2Element): boolean; delete(): void; } export declare class PrivateKey { static PRIVATE_KEY_SIZE: number; - static from_bytes(bytes: Uint8Array, modOrder: boolean): PrivateKey; + static fromBytes(bytes: Uint8Array, modOrder: boolean): PrivateKey; static aggregate(pks: PrivateKey[]): PrivateKey; deepcopy(): PrivateKey; serialize(): Uint8Array; - get_g1(): G1Element; - get_g2(): G2Element; - mul_g1(el: G1Element): G1Element; - mul_g2(el: G2Element): G2Element; - equal_to(key: PrivateKey): boolean; + getG1(): G1Element; + getG2(): G2Element; + mulG1(el: G1Element): G1Element; + mulG2(el: G2Element): G2Element; + equalTo(key: PrivateKey): boolean; delete(): void; } export declare class Bignum { - static from_string(s: string, radix: number): Bignum; + static fromString(s: string, radix: number): Bignum; toString(radix: number): string; delete(): void; } export declare class Util { static hash256(msg: Uint8Array): Uint8Array; - static hex_str(msg: Uint8Array): string; + static hexStr(msg: Uint8Array): string; } export interface ModuleInstance { diff --git a/src/dashbls/js-bindings/bundle_wasm_for_web.js b/src/dashbls/js-bindings/bundle_wasm_for_web.js new file mode 100644 index 0000000000..cfd67d56d4 --- /dev/null +++ b/src/dashbls/js-bindings/bundle_wasm_for_web.js @@ -0,0 +1,37 @@ +// The code manipulation from this file needs to be done for Chrome, as +// it requires wasm to be loaded asynchronously, and it doesn't +// work when bundling complex projects. With this solution, wasm is +// included right into the bundle itself in a form of base64 string +// and compiled asynchronously, just as Chrome requires + +const fs = require('fs'); + +const outputPath = './blsjs.js'; + +const wasm = fs.readFileSync('./blsjstmp.wasm'); +const wasmBase = wasm.toString('base64'); + +const codeToPrepend = ` +if (typeof window === "object") { + var buf = Buffer.from("${wasmBase}", "base64"); + var blob = new Blob([buf], { type: "application/wasm" }); + var wasmUrl = URL.createObjectURL(blob); +} +`; + +const originalSourceCode = fs.readFileSync('./blsjstmp.js', 'utf-8'); +const modifiedSourceCode = originalSourceCode + .replace(/fetch\(.,/g, "fetch(wasmUrl,"); + +const modifiedSourceBuffer = Buffer.from(modifiedSourceCode, 'utf-8'); + +const bundleFileDescriptor = fs.openSync(outputPath, 'w+'); + +const bufferToPrepend = Buffer.from(codeToPrepend); + +fs.writeSync(bundleFileDescriptor, bufferToPrepend, 0, bufferToPrepend.length, 0); +fs.writeSync(bundleFileDescriptor, modifiedSourceBuffer, 0, modifiedSourceBuffer.length, bufferToPrepend.length); + +fs.close(bundleFileDescriptor, (err) => { + if (err) throw err; +}); diff --git a/src/dashbls/js-bindings/jsbindings.cpp b/src/dashbls/js-bindings/jsbindings.cpp index 038f55ce52..f390923eb8 100644 --- a/src/dashbls/js-bindings/jsbindings.cpp +++ b/src/dashbls/js-bindings/jsbindings.cpp @@ -22,92 +22,88 @@ using namespace emscripten; namespace js_wrappers { EMSCRIPTEN_BINDINGS(blsjs) { class_("AugSchemeMPL") - .class_function("sk_to_g1", &AugSchemeMPLWrapper::SkToG1) - .class_function("key_gen", &AugSchemeMPLWrapper::KeyGen) + .class_function("skToG1", &AugSchemeMPLWrapper::SkToG1) + .class_function("keyGen", &AugSchemeMPLWrapper::KeyGen) .class_function("sign", &AugSchemeMPLWrapper::Sign) - .class_function("sign_prepend", &AugSchemeMPLWrapper::SignPrepend) + .class_function("signPrepend", &AugSchemeMPLWrapper::SignPrepend) .class_function("verify", &AugSchemeMPLWrapper::Verify) .class_function("aggregate", &AugSchemeMPLWrapper::Aggregate) - .class_function("aggregate_verify", &AugSchemeMPLWrapper::AggregateVerify) - .class_function("derive_child_sk", &AugSchemeMPLWrapper::DeriveChildSk) - .class_function("derive_child_sk_unhardened", &AugSchemeMPLWrapper::DeriveChildSkUnhardened) - .class_function("derive_child_pk_unhardened", &AugSchemeMPLWrapper::DeriveChildPkUnhardened); + .class_function("aggregateVerify", &AugSchemeMPLWrapper::AggregateVerify) + .class_function("deriveChildSk", &AugSchemeMPLWrapper::DeriveChildSk) + .class_function("deriveChildSkUnhardened", &AugSchemeMPLWrapper::DeriveChildSkUnhardened) + .class_function("deriveChildPkUnhardened", &AugSchemeMPLWrapper::DeriveChildPkUnhardened); class_>("BasicSchemeMPL") - .class_function("sk_to_g1", &SchemeMPLWrapper::SkToG1) - .class_function("key_gen", &SchemeMPLWrapper::KeyGen) + .class_function("skToG1", &SchemeMPLWrapper::SkToG1) + .class_function("keyGen", &SchemeMPLWrapper::KeyGen) .class_function("sign", &SchemeMPLWrapper::Sign) .class_function("verify", &SchemeMPLWrapper::Verify) .class_function("aggregate", &SchemeMPLWrapper::Aggregate) - .class_function("aggregate_verify", &SchemeMPLWrapper::AggregateVerify) - .class_function("derive_child_sk", &SchemeMPLWrapper::DeriveChildSk) - .class_function("derive_child_sk_unhardened", &SchemeMPLWrapper::DeriveChildSkUnhardened) - .class_function("derive_child_pk_unhardened", &SchemeMPLWrapper::DeriveChildPkUnhardened); + .class_function("aggregateVerify", &SchemeMPLWrapper::AggregateVerify) + .class_function("deriveChildSk", &SchemeMPLWrapper::DeriveChildSk) + .class_function("deriveChildSkUnhardened", &SchemeMPLWrapper::DeriveChildSkUnhardened) + .class_function("deriveChildPkUnhardened", &SchemeMPLWrapper::DeriveChildPkUnhardened); class_("PopSchemeMPL") - .class_function("sk_to_g1", &PopSchemeMPLWrapper::SkToG1) - .class_function("key_gen", &PopSchemeMPLWrapper::KeyGen) + .class_function("skToG1", &PopSchemeMPLWrapper::SkToG1) + .class_function("keyGen", &PopSchemeMPLWrapper::KeyGen) .class_function("sign", &PopSchemeMPLWrapper::Sign) .class_function("verify", &PopSchemeMPLWrapper::Verify) .class_function("aggregate", &PopSchemeMPLWrapper::Aggregate) - .class_function("aggregate_verify", &PopSchemeMPLWrapper::AggregateVerify) - .class_function("derive_child_sk", &PopSchemeMPLWrapper::DeriveChildSk) - .class_function("derive_child_sk_unhardened", &PopSchemeMPLWrapper::DeriveChildSkUnhardened) - .class_function("derive_child_pk_unhardened", &PopSchemeMPLWrapper::DeriveChildPkUnhardened) - .class_function("pop_prove", &PopSchemeMPLWrapper::PopProve) - .class_function("pop_verify", &PopSchemeMPLWrapper::PopVerify) - .class_function("fast_aggregate_verify", &PopSchemeMPLWrapper::FastAggregateVerify); + .class_function("aggregateVerify", &PopSchemeMPLWrapper::AggregateVerify) + .class_function("deriveChildSk", &PopSchemeMPLWrapper::DeriveChildSk) + .class_function("deriveChildSkUnhardened", &PopSchemeMPLWrapper::DeriveChildSkUnhardened) + .class_function("deriveChildPkUnhardened", &PopSchemeMPLWrapper::DeriveChildPkUnhardened) + .class_function("popProve", &PopSchemeMPLWrapper::PopProve) + .class_function("popVerify", &PopSchemeMPLWrapper::PopVerify) + .class_function("fastAggregateVerify", &PopSchemeMPLWrapper::FastAggregateVerify); class_("G1Element") .class_property("SIZE", &G1ElementWrapper::SIZE) .constructor<>() - .class_function("fromBytes", &G1ElementWrapper::FromBytes) // Not removing this for compatibility - .class_function("from_bytes", &G1ElementWrapper::FromBytes) + .class_function("fromBytes", &G1ElementWrapper::FromBytes) .class_function("generator", &G2ElementWrapper::Generator) .function("serialize", &G1ElementWrapper::Serialize) .function("negate", &G1ElementWrapper::Negate) .function("deepcopy", &G1ElementWrapper::Deepcopy) - .function("get_fingerprint", &G1ElementWrapper::GetFingerprint) + .function("getFingerprint", &G1ElementWrapper::GetFingerprint) .function("add", &G1ElementWrapper::Add) .function("mul", &G1ElementWrapper::Mul) - .function("equal_to", &G1ElementWrapper::EqualTo); + .function("equalTo", &G1ElementWrapper::EqualTo); class_("G2Element") .class_property("SIZE", &G2ElementWrapper::SIZE) .constructor<>() - .class_function("fromBytes", &G2ElementWrapper::FromBytes) // Not removing this for compatibility - .class_function("from_bytes", &G2ElementWrapper::FromBytes) - .class_function("from_g2", &G2ElementWrapper::FromG2Element) - .class_function("aggregate_sigs", &G2ElementWrapper::AggregateSigs) + .class_function("fromBytes", &G2ElementWrapper::FromBytes) + .class_function("fromG2", &G2ElementWrapper::FromG2Element) + .class_function("aggregateSigs", &G2ElementWrapper::AggregateSigs) .class_function("generator", &G2ElementWrapper::Generator) .function("serialize", &G2ElementWrapper::Serialize) .function("negate", &G2ElementWrapper::Negate) .function("deepcopy", &G2ElementWrapper::Deepcopy) .function("add", &G2ElementWrapper::Add) .function("mul", &G2ElementWrapper::Mul) - .function("equal_to", &G2ElementWrapper::EqualTo); + .function("equalTo", &G2ElementWrapper::EqualTo); class_("PrivateKey") .class_property("PRIVATE_KEY_SIZE", &PrivateKeyWrapper::PRIVATE_KEY_SIZE) - .class_function("fromBytes", &PrivateKeyWrapper::FromBytes) // Not removing this for compatibility - .class_function("from_bytes", &PrivateKeyWrapper::FromBytes) + .class_function("fromBytes", &PrivateKeyWrapper::FromBytes) .class_function("aggregate", &PrivateKeyWrapper::Aggregate) .function("deepcopy", &PrivateKeyWrapper::Deepcopy) .function("serialize", &PrivateKeyWrapper::Serialize) - .function("get_g1", &PrivateKeyWrapper::GetG1) - .function("get_g2", &PrivateKeyWrapper::GetG2) - .function("mul_g1", &PrivateKeyWrapper::MulG1) - .function("mul_g2", &PrivateKeyWrapper::MulG2) - .function("equal_to", &PrivateKeyWrapper::EqualTo); + .function("getG1", &PrivateKeyWrapper::GetG1) + .function("getG2", &PrivateKeyWrapper::GetG2) + .function("mulG1", &PrivateKeyWrapper::MulG1) + .function("mulG2", &PrivateKeyWrapper::MulG2) + .function("equalTo", &PrivateKeyWrapper::EqualTo); class_("Bignum") - .class_function("fromString", &BignumWrapper::FromString) // Not removing this for compatibility - .class_function("from_string", &BignumWrapper::FromString) + .class_function("fromString", &BignumWrapper::FromString) .function("toString", &BignumWrapper::ToString); class_("Util") .class_function("hash256", &UtilWrapper::Hash256) - .class_function("hex_str", &UtilWrapper::HexStr); + .class_function("hexStr", &UtilWrapper::HexStr); }; } // namespace js_wrappers diff --git a/src/dashbls/js-bindings/package-lock.json b/src/dashbls/js-bindings/package-lock.json index 5d2a395f19..33a83eb635 100644 --- a/src/dashbls/js-bindings/package-lock.json +++ b/src/dashbls/js-bindings/package-lock.json @@ -1,19 +1,4221 @@ { - "name": "bls-signatures", - "version": "0.2.1-beta.0", - "lockfileVersion": 1, + "name": "@dashevo/bls", + "version": "1.0.0-beta.3", + "lockfileVersion": 2, "requires": true, - "dependencies": { - "@socket.io/base64-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", + "packages": { + "": { + "name": "@dashevo/bls", + "version": "1.0.0-beta.3", + "dependencies": { + "binascii": "0.0.2" + }, + "devDependencies": { + "@types/mocha": "^5.2.7", + "@types/node": "^11.15.18", + "assert": "^2.0.0", + "babel-polyfill": "^6.26.0", + "buffer": "^6.0.3", + "crypto-browserify": "^3.12.0", + "karma": "^6.3.4", + "karma-firefox-launcher": "^1.3.0", + "karma-mocha": "^2.0.1", + "karma-mocha-reporter": "^2.2.5", + "karma-webpack": "^5.0.0", + "mime": "1.4.1", + "mocha": "^8.4.0", + "path-browserify": "^1.0.1", + "process": "^0.11.10", + "stream-browserify": "^3.0.0", + "typescript": "^3.6.5", + "webpack": "^5.39.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, - "@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", + "dev": true + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "node_modules/@types/cors": { + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/eslint": { + "version": "7.2.13", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.13.tgz", + "integrity": "sha512-LKmQCWAlnVHvvXq4oasNUMTJJb2GwSyTY8+1C7OH5ILR8mPLaljv1jxL1bXW3xB3jFbQxTKxJAvI8PyjB09aBg==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.0.tgz", + "integrity": "sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "0.0.47", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.47.tgz", + "integrity": "sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", + "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", + "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "11.15.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.15.18.tgz", + "integrity": "sha512-3p2M6moxwdDFyPia2ROI8CCkRa9ZzYjvCys2TOE1xgwYDQmY49Cj0cvkdBkzh/rY9gkvzgzYOeECYtB4f0/fDA==", + "dev": true + }, + "node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", + "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", + "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", + "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", + "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", + "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.0", + "@webassemblyjs/helper-api-error": "1.11.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", + "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", + "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", + "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", + "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", + "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", + "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/helper-wasm-section": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0", + "@webassemblyjs/wasm-opt": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0", + "@webassemblyjs/wast-printer": "1.11.0" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", + "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/ieee754": "1.11.0", + "@webassemblyjs/leb128": "1.11.0", + "@webassemblyjs/utf8": "1.11.0" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", + "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", + "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-api-error": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/ieee754": "1.11.0", + "@webassemblyjs/leb128": "1.11.0", + "@webassemblyjs/utf8": "1.11.0" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", + "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/assert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", + "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", + "dev": true, + "dependencies": { + "es6-object-assign": "^1.1.0", + "is-nan": "^1.2.1", + "object-is": "^1.0.1", + "util": "^0.12.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz", + "integrity": "sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + } + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/babel-runtime/node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true, + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/binascii": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/binascii/-/binascii-0.0.2.tgz", + "integrity": "sha1-p/iogB28z4sXVrdD2qD+6eLZ4O4=" + }, + "node_modules/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + }, + "node_modules/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.7", + "raw-body": "2.4.3", + "type-is": "~1.6.18" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/browserify-sign/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/browserify-sign/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/browserslist": { + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30001219", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.723", + "escalade": "^3.1.1", + "node-releases": "^1.1.71" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001237", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001237.tgz", + "integrity": "sha512-pDHgRndit6p1NR2GhzMbQ6CkRrp4VKuSsqbcLeOQppYPKOYkKT/6ZvZDvKJUqcmtyWIAHuZq3SVS2vc1egCZzw==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "dev": true, + "hasInstallScript": true + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "node_modules/date-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", + "integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "dependencies": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.3.752", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.752.tgz", + "integrity": "sha512-2Tg+7jSl3oPxgsBsWKh5H83QazTkmWG/cnNwJplmyZc7KcN61+I10oUgaXSVk/NwfvN3BdkKDR4FYuRBQQ2v0A==", + "dev": true + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/elliptic/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/engine.io": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.0.tgz", + "integrity": "sha512-OgxY1c/RuCSeO/rTr8DIFXx76IzUUft86R7/P7MMbbkuzeqJoTNw2lmeD91IyGz41QYleIIjWeMJGgug043sfQ==", + "dev": true, + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.11.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", + "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/enhanced-resolve": { + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz", + "integrity": "sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "node_modules/es-abstract": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", + "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.10.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract/node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract/node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-abstract/node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-module-lexer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz", + "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==", + "dev": true + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "node_modules/fs-extra": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic/node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/hash-base/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/is-arguments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", + "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", + "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.0.0.tgz", + "integrity": "sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz", + "integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex/node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol/node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", + "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.2", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.0-next.2", + "foreach": "^2.0.5", + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array/node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isbinaryfile": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz", + "integrity": "sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w==", + "dev": true, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/jest-worker": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.0.2.tgz", + "integrity": "sha512-EoBdilOTTyOgmHXtw/cPc+ZrCA0KJMrkXzkrPGNwLmnvvlN1nj7MPrxpT7m+otSv2e1TLaVffzDnE/LB14zJMg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/karma": { + "version": "6.3.16", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.16.tgz", + "integrity": "sha512-nEU50jLvDe5yvXqkEJRf8IuvddUkOY2x5Xc4WXHz6dxINgGDrgD2uqQWeVrJs4hbfNaotn+HQ1LZJ4yOXrL7xQ==", + "dev": true, + "dependencies": { + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "colors": "1.4.0", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.2.0", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "bin": { + "karma": "bin/karma" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/karma-firefox-launcher": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.3.0.tgz", + "integrity": "sha512-Fi7xPhwrRgr+94BnHX0F5dCl1miIW4RHnzjIGxF8GaIEp7rNqX7LSi7ok63VXs3PS/5MQaQMhGxw+bvD+pibBQ==", + "dev": true, + "dependencies": { + "is-wsl": "^2.1.0" + } + }, + "node_modules/karma-mocha": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-2.0.1.tgz", + "integrity": "sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.3" + } + }, + "node_modules/karma-mocha-reporter": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz", + "integrity": "sha1-FRIAlejtgZGG5HoLAS8810GJVWA=", + "dev": true, + "dependencies": { + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "strip-ansi": "^4.0.0" + }, + "peerDependencies": { + "karma": ">=0.13" + } + }, + "node_modules/karma-webpack": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-5.0.0.tgz", + "integrity": "sha512-+54i/cd3/piZuP3dr54+NcFeKOPnys5QeM1IY+0SPASwrtHsliXUiCL50iW+K9WWA7RvamC4macvvQ86l3KtaA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "webpack-merge": "^4.1.5" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/karma/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/karma/node_modules/graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "dev": true + }, + "node_modules/karma/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "dependencies": { + "chalk": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log4js": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz", + "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", + "dev": true, + "dependencies": { + "date-format": "^4.0.3", + "debug": "^4.3.3", + "flatted": "^3.2.4", + "rfdc": "^1.3.0", + "streamroller": "^3.0.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/log4js/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/log4js/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true, + "bin": { + "mime": "cli.js" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 10.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/mocha/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/mocha/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/mocha/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/mocha/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/mocha/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mocha/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "1.1.73", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", + "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", + "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", + "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true, + "engines": { + "node": ">=0.9" + } + }, + "node_modules/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", + "dev": true, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/socket.io": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.0.tgz", + "integrity": "sha512-b65bp6INPk/BMMrIgVvX12x3Q+NqlGqSlTuvKQWt0BUJ3Hyy3JangBl7fEoWZTXbOKlCqNPbQ6MbWgok/km28w==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.4.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dev": true, + "dependencies": { + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", + "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "dev": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-browserify/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/streamroller": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz", + "integrity": "sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==", + "dev": true, + "dependencies": { + "date-format": "^4.0.3", + "debug": "^4.1.1", + "fs-extra": "^10.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/streamroller/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/streamroller/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-color/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tapable": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz", + "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.16.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", + "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.3.tgz", + "integrity": "sha512-cxGbMqr6+A2hrIB5ehFIF+F/iST5ZOxvOmy9zih9ySbP1C2oEWQSOUS+2SNBTjzx5xLKO4xnod9eywdfq1Nb9A==", + "dev": true, + "dependencies": { + "jest-worker": "^27.0.2", + "p-limit": "^3.1.0", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.7.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", + "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ua-parser-js": { + "version": "0.7.33", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz", + "integrity": "sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unbox-primitive/node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz", + "integrity": "sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack": { + "version": "5.39.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.39.0.tgz", + "integrity": "sha512-25CHmuDj+oOTyteI13sUqNlCnjCnySuhiKWE/cRYPQYeoQ3ijHgyWX27CiyUKLNGq27v8S0mrksyTreT/xo7pg==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.0", + "@types/estree": "^0.0.47", + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/wasm-edit": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0", + "acorn": "^8.2.1", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.8.0", + "es-module-lexer": "^0.4.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.4", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.1", + "watchpack": "^2.2.0", + "webpack-sources": "^2.3.0" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-merge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + } + }, + "node_modules/webpack-sources": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.0.tgz", + "integrity": "sha512-WyOdtwSvOML1kbgtXbTDnEW0jkJ7hZr/bDByIwszhWd/4XX1A3XMkrbFMsuH4+/MfLlZCUzlAdg4r7jaGKEIgQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.4.tgz", + "integrity": "sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.2", + "call-bind": "^1.0.0", + "es-abstract": "^1.18.0-next.1", + "foreach": "^2.0.5", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.1", + "is-typed-array": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array/node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs-unparser/node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", "dev": true }, "@types/cookie": { @@ -23,10 +4225,13 @@ "dev": true }, "@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", - "dev": true + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dev": true, + "requires": { + "@types/node": "*" + } }, "@types/eslint": { "version": "7.2.13", @@ -244,29 +4449,12 @@ "requires": { "mime-types": "~2.1.34", "negotiator": "0.6.3" - }, - "dependencies": { - "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "dev": true - }, - "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dev": true, - "requires": { - "mime-db": "1.51.0" - } - } } }, "acorn": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.0.tgz", - "integrity": "sha512-ULr0LDaEqQrMFGyQ3bhJkLsbtrQ8QibAseGZeaSUiT/6zb9IvIkomWHJIvgvwad+hinRAgsI51JcWk2yvwyL+w==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true }, "ajv": { @@ -285,7 +4473,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} }, "ansi-colors": { "version": "4.1.1", @@ -577,9 +4766,9 @@ } }, "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, "buffer-xor": { @@ -748,12 +4937,6 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1007,9 +5190,9 @@ "dev": true }, "engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.0.tgz", + "integrity": "sha512-OgxY1c/RuCSeO/rTr8DIFXx76IzUUft86R7/P7MMbbkuzeqJoTNw2lmeD91IyGz41QYleIIjWeMJGgug043sfQ==", "dev": true, "requires": { "@types/cookie": "^0.4.1", @@ -1021,13 +5204,13 @@ "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" + "ws": "~8.11.0" }, "dependencies": { "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -1042,13 +5225,10 @@ } }, "engine.io-parser": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", - "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", - "dev": true, - "requires": { - "@socket.io/base64-arraybuffer": "~1.0.2" - } + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", + "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", + "dev": true }, "enhanced-resolve": { "version": "5.8.2", @@ -1946,18 +6126,18 @@ "dev": true }, "mime-db": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", - "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true }, "mime-types": { - "version": "2.1.30", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", - "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "requires": { - "mime-db": "1.47.0" + "mime-db": "1.52.0" } }, "minimalistic-assert": { @@ -2153,15 +6333,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, "p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", @@ -2185,15 +6356,6 @@ "requires": { "picomatch": "^2.2.1" } - }, - "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } } } }, @@ -2236,7 +6398,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true }, "object-inspect": { @@ -2533,17 +6695,17 @@ } }, "socket.io": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", - "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.0.tgz", + "integrity": "sha512-b65bp6INPk/BMMrIgVvX12x3Q+NqlGqSlTuvKQWt0BUJ3Hyy3JangBl7fEoWZTXbOKlCqNPbQ6MbWgok/km28w==", "dev": true, "requires": { "accepts": "~1.3.4", "base64id": "~2.0.0", "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", - "socket.io-parser": "~4.0.4" + "engine.io": "~6.4.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.1" }, "dependencies": { "debug": { @@ -2564,26 +6726,28 @@ } }, "socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", - "dev": true - }, - "socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", "dev": true, "requires": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", + "ws": "~8.11.0" + } + }, + "socket.io-parser": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", + "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "dev": true, + "requires": { + "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" }, "dependencies": { "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -2610,21 +6774,13 @@ "dev": true }, "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, "statuses": { @@ -2679,6 +6835,23 @@ } } }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -2709,23 +6882,6 @@ "define-properties": "^1.1.3" } }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -2773,22 +6929,15 @@ "dev": true }, "terser": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.0.tgz", - "integrity": "sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g==", + "version": "5.16.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", + "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", "dev": true, "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.19" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } + "source-map-support": "~0.5.20" } }, "terser-webpack-plugin": { @@ -2803,14 +6952,6 @@ "serialize-javascript": "^5.0.1", "source-map": "^0.6.1", "terser": "^5.7.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, "tmp": { @@ -2854,9 +6995,9 @@ "dev": true }, "ua-parser-js": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", - "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", + "version": "0.7.33", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz", + "integrity": "sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw==", "dev": true }, "unbox-primitive": { @@ -2929,7 +7070,7 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true }, "void-elements": { @@ -2996,14 +7137,6 @@ "requires": { "source-list-map": "^2.0.1", "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, "which": { @@ -3136,10 +7269,11 @@ "dev": true }, "ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", - "dev": true + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, + "requires": {} }, "yargs": { "version": "16.2.0", diff --git a/src/dashbls/js-bindings/package.json b/src/dashbls/js-bindings/package.json index 93e9ca6e6c..2a4faebb7b 100644 --- a/src/dashbls/js-bindings/package.json +++ b/src/dashbls/js-bindings/package.json @@ -1,28 +1,31 @@ { - "name": "bls-signatures", - "version": "0.2.1-beta.0", + "name": "@dashevo/bls", + "version": "1.0.0-beta.3", "description": "The most advanced BLS library for JavaScript", "main": "blsjs.js", "types": "blsjs.d.ts", "files": [ "blsjs.js", - "blsjs.wasm", + "blsjstmp.wasm", "blsjs.d.ts" ], "directories": { "test": "tests" }, "scripts": { + "build:web": "node bundle_wasm_for_web.js", "test": "npm run test:node && npm run test:browser", - "test:typings": "tsc --esModuleInterop ./tests/typings.spec.ts", - "test:node": "npm run test:typings && mocha ./tests/*.spec.js", - "test:browser": "npm run test:typings && ./node_modules/.bin/karma start ./tests/karma.conf.js --single-run" + "test:typings": "tsc ./tests/typings.spec.ts", + "test:node": "mocha ./tests/*.spec.js", + "test:browser": "npm run test:typings && karma start ./tests/karma.conf.js --single-run", + "webpack": "webpack --config=./webpack.config.js", + "rollup": "rollup -c" }, "repository": { "type": "git", - "url": "git@github.com:Chia-Network/bls-signatures.git" + "url": "git@github.com:dashpay/bls-signatures.git" }, - "homepage": "https://github.com/Chia-Network/bls-signatures/tree/master/js-bindings", + "homepage": "https://github.com/dashpay/bls-signatures/tree/main/js-bindings", "author": { "name": "Anton Suprunchuk", "email": "antouhou@gmail.com", diff --git a/src/dashbls/js-bindings/tests/PrivateKey.spec.js b/src/dashbls/js-bindings/tests/PrivateKey.spec.js index 7980693752..b25bf40e64 100644 --- a/src/dashbls/js-bindings/tests/PrivateKey.spec.js +++ b/src/dashbls/js-bindings/tests/PrivateKey.spec.js @@ -56,8 +56,8 @@ describe('PrivateKey', () => { const message1 = Uint8Array.from([1, 65, 254, 88, 90, 45, 22]); const seed = Uint8Array.from([28, 20, 102, 229, 1, 157]); - const sk1 = AugSchemeMPL.key_gen(getPkSeed()); - const pk1 = AugSchemeMPL.sk_to_g1(sk1); + const sk1 = AugSchemeMPL.keyGen(getPkSeed()); + const pk1 = AugSchemeMPL.skToG1(sk1); const sig1 = AugSchemeMPL.sign(sk1, message1); assert(AugSchemeMPL.verify(pk1, message1, sig1)); @@ -67,7 +67,7 @@ describe('PrivateKey', () => { it('Should create a private key from a seed', () => { const {AugSchemeMPL, PrivateKey} = blsSignatures; - const pk = AugSchemeMPL.key_gen(getPkSeed()); + const pk = AugSchemeMPL.keyGen(getPkSeed()); assert(pk instanceof PrivateKey); assert.deepStrictEqual(pk.serialize(), getPkBuffer()); }); @@ -77,14 +77,14 @@ describe('PrivateKey', () => { it('Should create a private key from a Buffer', () => { const {PrivateKey, Util} = blsSignatures; - const pk = PrivateKey.from_bytes(getPkBuffer(), false); + const pk = PrivateKey.fromBytes(getPkBuffer(), false); assert(pk instanceof PrivateKey); assert.deepStrictEqual(pk.serialize(), getPkBuffer()); }); it('Should create a private key from a Uint8Array', () => { const {PrivateKey, Util} = blsSignatures; - const pk = PrivateKey.from_bytes(getPkUint8Array(), false); + const pk = PrivateKey.fromBytes(getPkUint8Array(), false); assert(pk instanceof PrivateKey); assert.deepStrictEqual(pk.serialize(), getPkBuffer()); }); @@ -94,7 +94,7 @@ describe('PrivateKey', () => { it('Should serialize key to a Buffer', () => { const {AugSchemeMPL, PrivateKey} = blsSignatures; - const pk = AugSchemeMPL.key_gen(getPkSeed()); + const pk = AugSchemeMPL.keyGen(getPkSeed()); const serialized = pk.serialize(); assert(serialized instanceof Uint8Array); assert.deepStrictEqual(serialized, getPkBuffer()); @@ -106,7 +106,7 @@ describe('PrivateKey', () => { const {AugSchemeMPL, PrivateKey, G2Element} = blsSignatures; const pk = PrivateKey.fromBytes(getPkBuffer(), false); - const pubkey = AugSchemeMPL.sk_to_g1(pk); + const pubkey = AugSchemeMPL.skToG1(pk); const message = 'Hello world'; const messageBuffer = Uint8Array.from(Buffer.from(message, 'utf8')); const signature = AugSchemeMPL.sign(pk, messageBuffer); @@ -119,10 +119,10 @@ describe('PrivateKey', () => { it('Should return a public key with a verifiable fingerprint', () => { const {AugSchemeMPL, PrivateKey, G1Element} = blsSignatures; - const pk = AugSchemeMPL.key_gen(getPkSeed()); - const publicKey = AugSchemeMPL.sk_to_g1(pk); + const pk = AugSchemeMPL.keyGen(getPkSeed()); + const publicKey = AugSchemeMPL.skToG1(pk); assert(publicKey instanceof G1Element); - assert.strictEqual(publicKey.get_fingerprint(), getSeedAndFinferprint().fingerprint); + assert.strictEqual(publicKey.getFingerprint(), getSeedAndFinferprint().fingerprint); }); }); }); diff --git a/src/dashbls/js-bindings/tests/PublicKey.spec.js b/src/dashbls/js-bindings/tests/PublicKey.spec.js index 3effbbd988..835fe51927 100644 --- a/src/dashbls/js-bindings/tests/PublicKey.spec.js +++ b/src/dashbls/js-bindings/tests/PublicKey.spec.js @@ -41,11 +41,11 @@ before((done) => { }); describe('G1Element', () => { - describe('.from_bytes', () => { + describe('.fromBytes', () => { it('Should create a public key from bytes', () => { const {G1Element, Util} = blsSignatures; - const pk = G1Element.from_bytes(getPublicKeyFixture().buffer); + const pk = G1Element.fromBytes(getPublicKeyFixture().buffer); assert(pk instanceof G1Element); }); }); @@ -54,12 +54,12 @@ describe('G1Element', () => { it('Should aggregate keys if keys array contains more than one key', () => { const {G1Element} = blsSignatures; - const pks = getPublicKeysArray().map(buf => G1Element.from_bytes(buf)); - let first_pk = pks[0]; + const pks = getPublicKeysArray().map(buf => G1Element.fromBytes(buf)); + let firstPk = pks[0]; for (var i = 1; i < pks.length; i++) { - first_pk = first_pk.add(pks[i]); + firstPk = firstPk.add(pks[i]); } - assert(first_pk instanceof G1Element); + assert(firstPk instanceof G1Element); }); }); @@ -67,7 +67,7 @@ describe('G1Element', () => { it('Should serialize key to the same buffer', () => { const {G1Element} = blsSignatures; - const pk = G1Element.from_bytes(getPublicKeyFixture().buffer); + const pk = G1Element.fromBytes(getPublicKeyFixture().buffer); const serialized = pk.serialize(); assert.deepStrictEqual(Buffer.from(serialized).toString('hex'), getPublicKeyFixtureHex()); }); @@ -77,8 +77,8 @@ describe('G1Element', () => { it('Should get correct fingerprint', () => { const {G1Element} = blsSignatures; - const pk = G1Element.from_bytes(getPublicKeyFixture().buffer); - const fingerprint = pk.get_fingerprint(); + const pk = G1Element.fromBytes(getPublicKeyFixture().buffer); + const fingerprint = pk.getFingerprint(); assert.strictEqual(fingerprint, getPublicKeyFixture().fingerprint); }); }); diff --git a/src/dashbls/js-bindings/tests/Signature.spec.js b/src/dashbls/js-bindings/tests/Signature.spec.js index 555093bef8..dbec9e5f3e 100644 --- a/src/dashbls/js-bindings/tests/Signature.spec.js +++ b/src/dashbls/js-bindings/tests/Signature.spec.js @@ -38,13 +38,13 @@ describe('Signature', () => { const seed2 = makehash(Uint8Array.from([3, 4, 5, 6, 7])); const seed3 = makehash(Uint8Array.from([4, 5, 6, 7, 8])); - const privateKey1 = BasicSchemeMPL.key_gen(seed1); - const privateKey2 = BasicSchemeMPL.key_gen(seed2); - const privateKey3 = BasicSchemeMPL.key_gen(seed3); + const privateKey1 = BasicSchemeMPL.keyGen(seed1); + const privateKey2 = BasicSchemeMPL.keyGen(seed2); + const privateKey3 = BasicSchemeMPL.keyGen(seed3); - const publicKey1 = BasicSchemeMPL.sk_to_g1(privateKey1); - const publicKey2 = BasicSchemeMPL.sk_to_g1(privateKey2); - const publicKey3 = BasicSchemeMPL.sk_to_g1(privateKey3); + const publicKey1 = BasicSchemeMPL.skToG1(privateKey1); + const publicKey2 = BasicSchemeMPL.skToG1(privateKey2); + const publicKey3 = BasicSchemeMPL.skToG1(privateKey3); const sig1 = BasicSchemeMPL.sign(privateKey1, message); const sig2 = BasicSchemeMPL.sign(privateKey2, message); @@ -89,14 +89,14 @@ describe('Signature', () => { it('Should aggregate signature', () => { const {AugSchemeMPL, G2Element, PrivateKey} = blsSignatures; - const sk = AugSchemeMPL.key_gen(makehash(Uint8Array.from([1, 2, 3]))); - const pk = AugSchemeMPL.sk_to_g1(sk); + const sk = AugSchemeMPL.keyGen(makehash(Uint8Array.from([1, 2, 3]))); + const pk = AugSchemeMPL.skToG1(sk); const msg1 = Uint8Array.from([3, 4, 5]); const msg2 = Uint8Array.from([6, 7, 8]); const sig1 = AugSchemeMPL.sign(sk, msg1); const sig2 = AugSchemeMPL.sign(sk, msg2); - const aggregatedSig = G2Element.aggregate_sigs([sig1, sig2]); - assert.strictEqual(AugSchemeMPL.aggregate_verify([pk, pk], [msg1, msg2], aggregatedSig), true); + const aggregatedSig = G2Element.aggregateSigs([sig1, sig2]); + assert.strictEqual(AugSchemeMPL.aggregateVerify([pk, pk], [msg1, msg2], aggregatedSig), true); sk.delete(); pk.delete(); @@ -109,7 +109,7 @@ describe('Signature', () => { it('Should serialize signature to Buffer', () => { const {AugSchemeMPL, G2Element, PrivateKey} = blsSignatures; - const sk = AugSchemeMPL.key_gen(makehash(Uint8Array.from([1, 2, 3, 4, 5]))); + const sk = AugSchemeMPL.keyGen(makehash(Uint8Array.from([1, 2, 3, 4, 5]))); const sig = AugSchemeMPL.sign(sk, Uint8Array.from([100, 2, 254, 88, 90, 45, 23])); assert(sig instanceof G2Element); assert.deepStrictEqual(Buffer.from(sig.serialize()).toString('hex'), getSignatureHex()); @@ -125,15 +125,15 @@ describe('Signature', () => { const message = Uint8Array.from(Buffer.from('Message')); const seed1 = makehash(Buffer.from([1, 2, 3, 4, 5])); const seed2 = makehash(Buffer.from([1, 2, 3, 4, 6])); - const sk1 = AugSchemeMPL.key_gen(seed1); - const sk2 = AugSchemeMPL.key_gen(seed2); - const pk1 = AugSchemeMPL.sk_to_g1(sk1); - const pk2 = AugSchemeMPL.sk_to_g1(sk2); + const sk1 = AugSchemeMPL.keyGen(seed1); + const sk2 = AugSchemeMPL.keyGen(seed2); + const pk1 = AugSchemeMPL.skToG1(sk1); + const pk2 = AugSchemeMPL.skToG1(sk2); const sig1 = AugSchemeMPL.sign(sk1, message); const sig2 = AugSchemeMPL.sign(sk2, message); const sig = AugSchemeMPL.aggregate([sig1, sig2]); - assert(AugSchemeMPL.aggregate_verify([pk1, pk2], [message, message], sig)); + assert(AugSchemeMPL.aggregateVerify([pk1, pk2], [message, message], sig)); sk1.delete(); sk2.delete(); @@ -149,8 +149,8 @@ describe('Signature', () => { const message1 = Uint8Array.from(Buffer.from('Message')); const message2 = Uint8Array.from(Buffer.from('Nessage')); const seed = makehash(Buffer.from([1, 2, 3, 4, 5])); - const sk = AugSchemeMPL.key_gen(seed); - const pk = AugSchemeMPL.sk_to_g1(sk); + const sk = AugSchemeMPL.keyGen(seed); + const pk = AugSchemeMPL.skToG1(sk); const sig = AugSchemeMPL.sign(sk, message1); assert.strictEqual(AugSchemeMPL.verify(pk, message2, sig), false); diff --git a/src/dashbls/js-bindings/tests/test.js b/src/dashbls/js-bindings/tests/test.js index d87dee1017..34671d6546 100644 --- a/src/dashbls/js-bindings/tests/test.js +++ b/src/dashbls/js-bindings/tests/test.js @@ -50,7 +50,7 @@ blsjs().then((blsjs) => { Util } = blsjs; - function test_schemes() { + function testSchemes() { var seedArray = [ 0, 50, 6, 244, 24, 199, 1, 25, 52, 88, 192, 19, 18, 12, 89, 6, 220, 18, 102, 58, 209, 82, 12, 62, 89, 110, 182, 9, 44, 20, 254, 22 @@ -59,8 +59,8 @@ blsjs().then((blsjs) => { const msg = Buffer.from([100, 2, 254, 88, 90, 45, 23]); const msg2 = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); - const sk = BasicSchemeMPL.key_gen(seed); - const pk = sk.get_g1(); + const sk = BasicSchemeMPL.keyGen(seed); + const pk = sk.getG1(); //assert(sk == PrivateKey.fromBytes(sk.serialize(), false)); //assert(pk == G1Element.fromBytes(pk.serialize())); @@ -72,49 +72,49 @@ blsjs().then((blsjs) => { }); var seed = Buffer.concat([Buffer.from([1]), seed.slice(1)]); - const sk1 = BasicSchemeMPL.key_gen(seed); - const pk1 = sk1.get_g1(); + const sk1 = BasicSchemeMPL.keyGen(seed); + const pk1 = sk1.getG1(); var seed = Buffer.concat([Buffer.from([2]), seed.slice(1)]); - const sk2 = BasicSchemeMPL.key_gen(seed); - const pk2 = sk2.get_g1(); + const sk2 = BasicSchemeMPL.keyGen(seed); + const pk2 = sk2.getG1(); [BasicSchemeMPL, AugSchemeMPL, PopSchemeMPL].map((Scheme) => { // Aggregate same message - const agg_pk = pk1.add(pk2); + const aggPk = pk1.add(pk2); var sig1, sig2; if (Scheme === AugSchemeMPL) { - sig1 = Scheme.sign_prepend(sk1, msg, agg_pk); - sig2 = Scheme.sign_prepend(sk2, msg, agg_pk); + sig1 = Scheme.signPrepend(sk1, msg, aggPk); + sig2 = Scheme.signPrepend(sk2, msg, aggPk); } else { sig1 = Scheme.sign(sk1, msg); sig2 = Scheme.sign(sk2, msg); } - var agg_sig = Scheme.aggregate([sig1, sig2]); - assert(Scheme.verify(agg_pk, msg, agg_sig)); + var aggSig = Scheme.aggregate([sig1, sig2]); + assert(Scheme.verify(aggPk, msg, aggSig)); // Aggregate different message sig1 = Scheme.sign(sk1, msg) sig2 = Scheme.sign(sk2, msg2) - agg_sig = Scheme.aggregate([sig1, sig2]) - assert(Scheme.aggregate_verify([pk1, pk2], [msg, msg2], agg_sig)); + aggSig = Scheme.aggregate([sig1, sig2]) + assert(Scheme.aggregateVerify([pk1, pk2], [msg, msg2], aggSig)); // HD keys - const child = Scheme.derive_child_sk(sk1, 123); - const childU = Scheme.derive_child_sk_unhardened(sk1, 123); - const childUPk = Scheme.derive_child_pk_unhardened(pk1, 123); + const child = Scheme.deriveChildSk(sk1, 123); + const childU = Scheme.deriveChildSkUnhardened(sk1, 123); + const childUPk = Scheme.deriveChildPkUnhardened(pk1, 123); - const sig_child = Scheme.sign(child, msg); - assert(Scheme.verify(child.get_g1(), msg, sig_child)); + const sigChild = Scheme.sign(child, msg); + assert(Scheme.verify(child.getG1(), msg, sigChild)); - const sigU_child = Scheme.sign(childU, msg); - assert(Scheme.verify(childUPk, msg, sigU_child)); + const sigUChild = Scheme.sign(childU, msg); + assert(Scheme.verify(childUPk, msg, sigUChild)); }); } - function test_vectors_invalid() { + function testVectorsInvalid() { // Invalid inputs from https://github.com/algorand/bls_sigs_ref/blob/master/python-impl/serdesZ.py - const invalid_inputs_1 = [ + const invalidInputs1 = [ // infinity points: too short "c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", // infinity points: not all zeros @@ -131,7 +131,7 @@ blsjs().then((blsjs) => { // invalid elm of Fp --- equal to p (must be strictly less) "9a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", ] - const invalid_inputs_2 = [ + const invalidInputs2 = [ // infinity points: too short "c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", // infinity points: not all zeros @@ -151,36 +151,36 @@ blsjs().then((blsjs) => { "9a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", ]; - let g1_exn_count = 0; - let g2_exn_count = 0; + let g1ExnCount = 0; + let g2ExnCount = 0; - invalid_inputs_1.map((s) => { + invalidInputs1.map((s) => { const bytes_ = binascii.unhexlify(s); try { const g1 = G1Element(bytes_); console.log(`Failed to disallow creation of G1 element for string ${s}`); assert(false); } catch(e) { - g1_exn_count++; + g1ExnCount++; } }); - invalid_inputs_2.map((s) => { + invalidInputs2.map((s) => { const bytes_ = binascii.unhexlify(s); try { const g2 = G2Element(bytes_); console.log(`Failed to disallow creation of G2 element for string ${s}`); assert(false); } catch(e) { - g2_exn_count++; + g2ExnCount++; } }); - assert(g1_exn_count == invalid_inputs_1.length); - assert(g2_exn_count == invalid_inputs_2.length); + assert(g1ExnCount == invalidInputs1.length); + assert(g2ExnCount == invalidInputs2.length); } - function test_vectors_valid() { + function testVectorsValid() { // The following code was used to generate these vectors // // from py_ecc.bls import ( @@ -191,8 +191,8 @@ blsjs().then((blsjs) => { // // secret1 = bytes([1] * 32) // secret2 = bytes([x * 314159 % 256 for x in range(32)]) - // sk1 = int.from_bytes(secret1, 'big') - // sk2 = int.from_bytes(secret2, 'big') + // sk1 = int.fromBytes(secret1, 'big') + // sk2 = int.fromBytes(secret2, 'big') // msg = bytes([3, 1, 4, 1, 5, 9]) // pk1 = G2Basic.SkToPk(sk1) // pk2 = G2Basic.SkToPk(sk2) @@ -207,15 +207,15 @@ blsjs().then((blsjs) => { // // Javascript version converts these strings to binascii - const ref_sig1Basic = bytes('96ba34fac33c7f129d602a0bc8a3d43f9abc014eceaab7359146b4b150e57b808645738f35671e9e10e0d862a30cab70074eb5831d13e6a5b162d01eebe687d0164adbd0a864370a7c222a2768d7704da254f1bf1823665bc2361f9dd8c00e99'); - const ref_sig2Basic = bytes('a402790932130f766af11ba716536683d8c4cfa51947e4f9081fedd692d6dc0cac5b904bee5ea6e25569e36d7be4ca59069a96e34b7f700758b716f9494aaa59a96e74d14a3b552a9a6bc129e717195b9d6006fd6d5cef4768c022e0f7316abf'); - const ref_sigABasic = bytes('987cfd3bcd62280287027483f29c55245ed831f51dd6bd999a6ff1a1f1f1f0b647778b0167359c71505558a76e158e66181ee5125905a642246b01e7fa5ee53d68a4fe9bfb29a8e26601f0b9ad577ddd18876a73317c216ea61f430414ec51c5'); - const ref_sig1Aug = bytes('8180f02ccb72e922b152fcedbe0e1d195210354f70703658e8e08cbebf11d4970eab6ac3ccf715f3fb876df9a9797abd0c1af61aaeadc92c2cfe5c0a56c146cc8c3f7151a073cf5f16df38246724c4aed73ff30ef5daa6aacaed1a26ecaa336b'); - const ref_sig2Aug = bytes('99111eeafb412da61e4c37d3e806c6fd6ac9f3870e54da9222ba4e494822c5b7656731fa7a645934d04b559e9261b86201bbee57055250a459a2da10e51f9c1a6941297ffc5d970a557236d0bdeb7cf8ff18800b08633871a0f0a7ea42f47480'); - const ref_sigAAug = bytes('8c5d03f9dae77e19a5945a06a214836edb8e03b851525d84b9de6440e68fc0ca7303eeed390d863c9b55a8cf6d59140a01b58847881eb5af67734d44b2555646c6616c39ab88d253299acc1eb1b19ddb9bfcbe76e28addf671d116c052bb1847'); - const ref_sig1Pop = bytes('9550fb4e7f7e8cc4a90be8560ab5a798b0b23000b6a54a2117520210f986f3f281b376f259c0b78062d1eb3192b3d9bb049f59ecc1b03a7049eb665e0df36494ae4cb5f1136ccaeefc9958cb30c3333d3d43f07148c386299a7b1bfc0dc5cf7c'); - const ref_sig2Pop = bytes('a69036bc11ae5efcbf6180afe39addde7e27731ec40257bfdc3c37f17b8df68306a34ebd10e9e32a35253750df5c87c2142f8207e8d5654712b4e554f585fb6846ff3804e429a9f8a1b4c56b75d0869ed67580d789870babe2c7c8a9d51e7b2a'); - const ref_sigAPop = bytes('a4ea742bcdc1553e9ca4e560be7e5e6c6efa6a64dddf9ca3bb2854233d85a6aac1b76ec7d103db4e33148b82af9923db05934a6ece9a7101cd8a9d47ce27978056b0f5900021818c45698afdd6cf8a6b6f7fee1f0b43716f55e413d4b87a6039'); + const refSig1Basic = bytes('96ba34fac33c7f129d602a0bc8a3d43f9abc014eceaab7359146b4b150e57b808645738f35671e9e10e0d862a30cab70074eb5831d13e6a5b162d01eebe687d0164adbd0a864370a7c222a2768d7704da254f1bf1823665bc2361f9dd8c00e99'); + const refSig2Basic = bytes('a402790932130f766af11ba716536683d8c4cfa51947e4f9081fedd692d6dc0cac5b904bee5ea6e25569e36d7be4ca59069a96e34b7f700758b716f9494aaa59a96e74d14a3b552a9a6bc129e717195b9d6006fd6d5cef4768c022e0f7316abf'); + const refSigABasic = bytes('987cfd3bcd62280287027483f29c55245ed831f51dd6bd999a6ff1a1f1f1f0b647778b0167359c71505558a76e158e66181ee5125905a642246b01e7fa5ee53d68a4fe9bfb29a8e26601f0b9ad577ddd18876a73317c216ea61f430414ec51c5'); + const refSig1Aug = bytes('8180f02ccb72e922b152fcedbe0e1d195210354f70703658e8e08cbebf11d4970eab6ac3ccf715f3fb876df9a9797abd0c1af61aaeadc92c2cfe5c0a56c146cc8c3f7151a073cf5f16df38246724c4aed73ff30ef5daa6aacaed1a26ecaa336b'); + const refSig2Aug = bytes('99111eeafb412da61e4c37d3e806c6fd6ac9f3870e54da9222ba4e494822c5b7656731fa7a645934d04b559e9261b86201bbee57055250a459a2da10e51f9c1a6941297ffc5d970a557236d0bdeb7cf8ff18800b08633871a0f0a7ea42f47480'); + const refSigAAug = bytes('8c5d03f9dae77e19a5945a06a214836edb8e03b851525d84b9de6440e68fc0ca7303eeed390d863c9b55a8cf6d59140a01b58847881eb5af67734d44b2555646c6616c39ab88d253299acc1eb1b19ddb9bfcbe76e28addf671d116c052bb1847'); + const refSig1Pop = bytes('9550fb4e7f7e8cc4a90be8560ab5a798b0b23000b6a54a2117520210f986f3f281b376f259c0b78062d1eb3192b3d9bb049f59ecc1b03a7049eb665e0df36494ae4cb5f1136ccaeefc9958cb30c3333d3d43f07148c386299a7b1bfc0dc5cf7c'); + const refSig2Pop = bytes('a69036bc11ae5efcbf6180afe39addde7e27731ec40257bfdc3c37f17b8df68306a34ebd10e9e32a35253750df5c87c2142f8207e8d5654712b4e554f585fb6846ff3804e429a9f8a1b4c56b75d0869ed67580d789870babe2c7c8a9d51e7b2a'); + const refSigAPop = bytes('a4ea742bcdc1553e9ca4e560be7e5e6c6efa6a64dddf9ca3bb2854233d85a6aac1b76ec7d103db4e33148b82af9923db05934a6ece9a7101cd8a9d47ce27978056b0f5900021818c45698afdd6cf8a6b6f7fee1f0b43716f55e413d4b87a6039'); const secret1 = Buffer.from(repeat(32,1)); const secret2 = Buffer.from(range(32).map((x) => x * 314159 % 256)); @@ -233,18 +233,18 @@ blsjs().then((blsjs) => { const sig2Pop = PopSchemeMPL.sign(sk2, msg) const sigAPop = PopSchemeMPL.aggregate([sig1Pop, sig2Pop]) - assert(Buffer.from(sig1Basic.serialize()).equals(ref_sig1Basic)); - assert(Buffer.from(sig2Basic.serialize()).equals(ref_sig2Basic)); - assert(Buffer.from(sigABasic.serialize()).equals(ref_sigABasic)); - assert(Buffer.from(sig1Aug.serialize()).equals(ref_sig1Aug)); - assert(Buffer.from(sig2Aug.serialize()).equals(ref_sig2Aug)); - assert(Buffer.from(sigAAug.serialize()).equals(ref_sigAAug)); - assert(Buffer.from(sig1Pop.serialize()).equals(ref_sig1Pop)); - assert(Buffer.from(sig2Pop.serialize()).equals(ref_sig2Pop)); - assert(Buffer.from(sigAPop.serialize()).equals(ref_sigAPop)); + assert(Buffer.from(sig1Basic.serialize()).equals(refSig1Basic)); + assert(Buffer.from(sig2Basic.serialize()).equals(refSig2Basic)); + assert(Buffer.from(sigABasic.serialize()).equals(refSigABasic)); + assert(Buffer.from(sig1Aug.serialize()).equals(refSig1Aug)); + assert(Buffer.from(sig2Aug.serialize()).equals(refSig2Aug)); + assert(Buffer.from(sigAAug.serialize()).equals(refSigAAug)); + assert(Buffer.from(sig1Pop.serialize()).equals(refSig1Pop)); + assert(Buffer.from(sig2Pop.serialize()).equals(refSig2Pop)); + assert(Buffer.from(sigAPop.serialize()).equals(refSigAPop)); } - function test_readme() { + function testReadme() { let seed = Buffer.from( [ 0, @@ -281,8 +281,8 @@ blsjs().then((blsjs) => { 22, ] ); - let sk = AugSchemeMPL.key_gen(seed); - let pk = sk.get_g1(); + let sk = AugSchemeMPL.keyGen(seed); + let pk = sk.getG1(); const message = Buffer.from([1, 2, 3, 4, 5]); let signature = AugSchemeMPL.sign(sk, message); @@ -290,107 +290,107 @@ blsjs().then((blsjs) => { let ok = AugSchemeMPL.verify(pk, message, signature); assert(ok); - const sk_bytes = sk.serialize(); // 32 bytes - const pk_bytes = pk.serialize(); // 48 bytes - const signature_bytes = signature.serialize(); // 96 bytes + const skBytes = sk.serialize(); // 32 bytes + const pkBytes = pk.serialize(); // 48 bytes + const signatureBytes = signature.serialize(); // 96 bytes - console.log(Buffer.from(sk_bytes).toString('hex'), Buffer.from(pk_bytes).toString('hex'), Buffer.from(signature_bytes).toString('hex')); + console.log(Buffer.from(skBytes).toString('hex'), Buffer.from(pkBytes).toString('hex'), Buffer.from(signatureBytes).toString('hex')); - sk = PrivateKey.fromBytes(sk_bytes, false); - pk = G1Element.fromBytes(pk_bytes); - signature = G2Element.fromBytes(signature_bytes); + sk = PrivateKey.fromBytes(skBytes, false); + pk = G1Element.fromBytes(pkBytes); + signature = G2Element.fromBytes(signatureBytes); seed = Buffer.concat([Buffer.from([1]), seed.slice(1)]); - const sk1 = AugSchemeMPL.key_gen(seed); + const sk1 = AugSchemeMPL.keyGen(seed); seed = Buffer.concat([Buffer.from([2]), seed.slice(1)]); - const sk2 = AugSchemeMPL.key_gen(seed); + const sk2 = AugSchemeMPL.keyGen(seed); const message2 = Buffer.from([1, 2, 3, 4, 5, 6, 7]); - const pk1 = sk1.get_g1(); + const pk1 = sk1.getG1(); const sig1 = AugSchemeMPL.sign(sk1, message); - const pk2 = sk2.get_g1(); + const pk2 = sk2.getG1(); const sig2 = AugSchemeMPL.sign(sk2, message2); - const agg_sig = AugSchemeMPL.aggregate([sig1, sig2]); + const aggSig = AugSchemeMPL.aggregate([sig1, sig2]); - ok = AugSchemeMPL.aggregate_verify([pk1, pk2], [message, message2], agg_sig); + ok = AugSchemeMPL.aggregateVerify([pk1, pk2], [message, message2], aggSig); assert(ok); seed = Buffer.concat([Buffer.from([3]), seed.slice(1)]); - const sk3 = AugSchemeMPL.key_gen(seed); - const pk3 = sk3.get_g1(); + const sk3 = AugSchemeMPL.keyGen(seed); + const pk3 = sk3.getG1(); const message3 = Buffer.from([100, 2, 254, 88, 90, 45, 23]); const sig3 = AugSchemeMPL.sign(sk3, message3); - const agg_sig_final = AugSchemeMPL.aggregate([agg_sig, sig3]); - ok = AugSchemeMPL.aggregate_verify( - [pk1, pk2, pk3], [message, message2, message3], agg_sig_final + const aggSigFinal = AugSchemeMPL.aggregate([aggSig, sig3]); + ok = AugSchemeMPL.aggregateVerify( + [pk1, pk2, pk3], [message, message2, message3], aggSigFinal ); assert(ok); - const pop_sig1 = PopSchemeMPL.sign(sk1, message); - const pop_sig2 = PopSchemeMPL.sign(sk2, message); - const pop_sig3 = PopSchemeMPL.sign(sk3, message); - const pop1 = PopSchemeMPL.pop_prove(sk1); - const pop2 = PopSchemeMPL.pop_prove(sk2); - const pop3 = PopSchemeMPL.pop_prove(sk3); + const popSig1 = PopSchemeMPL.sign(sk1, message); + const popSig2 = PopSchemeMPL.sign(sk2, message); + const popSig3 = PopSchemeMPL.sign(sk3, message); + const pop1 = PopSchemeMPL.popProve(sk1); + const pop2 = PopSchemeMPL.popProve(sk2); + const pop3 = PopSchemeMPL.popProve(sk3); - ok = PopSchemeMPL.pop_verify(pk1, pop1); + ok = PopSchemeMPL.popVerify(pk1, pop1); assert(ok); - ok = PopSchemeMPL.pop_verify(pk2, pop2); + ok = PopSchemeMPL.popVerify(pk2, pop2); assert(ok); - ok = PopSchemeMPL.pop_verify(pk3, pop3); + ok = PopSchemeMPL.popVerify(pk3, pop3); assert(ok); - const pop_sig_agg = PopSchemeMPL.aggregate([pop_sig1, pop_sig2, pop_sig3]); + const popSigAgg = PopSchemeMPL.aggregate([popSig1, popSig2, popSig3]); - ok = PopSchemeMPL.fast_aggregate_verify([pk1, pk2, pk3], message, pop_sig_agg); + ok = PopSchemeMPL.fastAggregateVerify([pk1, pk2, pk3], message, popSigAgg); assert(ok); - const pop_agg_pk = pk1.add(pk2).add(pk3); - assert(Buffer.from(pop_agg_pk.serialize()).toString('hex') == '8ffb2a3c4a6ce516febdf1f2a5140c6974cce2530ebc1b56629f078c25d538aa3d8f0cf694516b4bfc8d344bbea829d3'); - const t_pop_agg_pk_1 = pk1.add(pk2.add(pk3)); - assert(Buffer.from(pop_agg_pk.serialize()).equals(Buffer.from(t_pop_agg_pk_1.serialize()))); + const popAggPk = pk1.add(pk2).add(pk3); + assert(Buffer.from(popAggPk.serialize()).toString('hex') == '8ffb2a3c4a6ce516febdf1f2a5140c6974cce2530ebc1b56629f078c25d538aa3d8f0cf694516b4bfc8d344bbea829d3'); + const tPopAggPk1 = pk1.add(pk2.add(pk3)); + assert(Buffer.from(popAggPk.serialize()).equals(Buffer.from(tPopAggPk1.serialize()))); - assert(Buffer.from(pop_sig_agg.serialize()).toString('hex') == 'b3115327c21286b043cf972db56cefe0a745a8091482c9eec47fe5c0dbdb2ffc4d05ae54e7ee45e209135e6c81e8af2212465abffe8ab3166d3f4d5ed1f4d98cb65323d8d1fc210311c7e46a5f637ef7d90b7f3206708dc4bb32a2e1549a3060'); - ok = PopSchemeMPL.verify(pop_agg_pk, message, pop_sig_agg); + assert(Buffer.from(popSigAgg.serialize()).toString('hex') == 'b3115327c21286b043cf972db56cefe0a745a8091482c9eec47fe5c0dbdb2ffc4d05ae54e7ee45e209135e6c81e8af2212465abffe8ab3166d3f4d5ed1f4d98cb65323d8d1fc210311c7e46a5f637ef7d90b7f3206708dc4bb32a2e1549a3060'); + ok = PopSchemeMPL.verify(popAggPk, message, popSigAgg); assert(ok); - const pop_agg_sk = PrivateKey.aggregate([sk1, sk2, sk3]); - ok = Buffer.from(PopSchemeMPL.sign(pop_agg_sk, message).serialize()).equals(Buffer.from(pop_sig_agg.serialize())); + const popAggSk = PrivateKey.aggregate([sk1, sk2, sk3]); + ok = Buffer.from(PopSchemeMPL.sign(popAggSk, message).serialize()).equals(Buffer.from(popSigAgg.serialize())); assert(ok); - const master_sk = AugSchemeMPL.key_gen(seed); - const child = AugSchemeMPL.derive_child_sk(master_sk, 152); - const grandchild = AugSchemeMPL.derive_child_sk(child, 952); + const masterSk = AugSchemeMPL.keyGen(seed); + const child = AugSchemeMPL.deriveChildSk(masterSk, 152); + const grandchild = AugSchemeMPL.deriveChildSk(child, 952); - const master_pk = master_sk.get_g1(); - const child_u = AugSchemeMPL.derive_child_sk_unhardened(master_sk, 22); - const grandchild_u = AugSchemeMPL.derive_child_sk_unhardened(child_u, 0); + const masterPk = masterSk.getG1(); + const childU = AugSchemeMPL.deriveChildSkUnhardened(masterSk, 22); + const grandchildU = AugSchemeMPL.deriveChildSkUnhardened(childU, 0); - const child_u_pk = AugSchemeMPL.derive_child_pk_unhardened(master_pk, 22); - const grandchild_u_pk = AugSchemeMPL.derive_child_pk_unhardened(child_u_pk, 0); + const childUPk = AugSchemeMPL.deriveChildPkUnhardened(masterPk, 22); + const grandchildUPk = AugSchemeMPL.deriveChildPkUnhardened(childUPk, 0); - ok = Buffer.from(grandchild_u_pk.serialize()).equals(Buffer.from(grandchild_u.get_g1().serialize())); + ok = Buffer.from(grandchildUPk.serialize()).equals(Buffer.from(grandchildU.getG1().serialize())); assert(ok); } - function test_aggregate_verify_zero_items() { - assert(AugSchemeMPL.aggregate_verify([], [], new G2Element())); + function testAggregateVerifyZeroItems() { + assert(AugSchemeMPL.aggregateVerify([], [], new G2Element())); } - function test_bignum() { + function testBignum() { const mersenne = Bignum.fromString('162259276829213363391578010288127', 10); assert(mersenne.toString(16).toLowerCase() == '7ffffffffffffffffffffffffff'); } - test_schemes(); - test_vectors_invalid(); - test_vectors_valid(); - test_readme(); - test_aggregate_verify_zero_items(); - test_bignum(); + testSchemes(); + testVectorsInvalid(); + testVectorsValid(); + testReadme(); + testAggregateVerifyZeroItems(); + testBignum(); }).then(function() { console.log("\nAll tests passed."); }); diff --git a/src/dashbls/js-bindings/tests/typings.spec.ts b/src/dashbls/js-bindings/tests/typings.spec.ts index ba18efe489..f84a93b92b 100644 --- a/src/dashbls/js-bindings/tests/typings.spec.ts +++ b/src/dashbls/js-bindings/tests/typings.spec.ts @@ -70,9 +70,9 @@ createBlsSignaturesModule().then((blsSignatures) => { describe('typings', () => { it('PrivateKey', () => { strictEqual(PrivateKey.PRIVATE_KEY_SIZE, 32); - const sk = AugSchemeMPL.key_gen(getSkSeed()); + const sk = AugSchemeMPL.keyGen(getSkSeed()); const aggSk = PrivateKey.aggregate([sk]); - const pk = sk.get_g1(); + const pk = sk.getG1(); const bytes: Uint8Array = sk.serialize(); const sig = AugSchemeMPL.sign(sk, getMessageBytes()); ok(AugSchemeMPL.verify(pk, getMessageBytes(), sig)); @@ -83,9 +83,9 @@ createBlsSignaturesModule().then((blsSignatures) => { it('G1Element', () => { strictEqual(G1Element.SIZE, 48); - const pk = G1Element.from_bytes(getPkBytes()); + const pk = G1Element.fromBytes(getPkBytes()); const aggPk = pk.add(pk); - const fingerprint: number = pk.get_fingerprint(); + const fingerprint: number = pk.getFingerprint(); const bytes: Uint8Array = pk.serialize(); pk.delete(); aggPk.delete(); @@ -93,10 +93,10 @@ createBlsSignaturesModule().then((blsSignatures) => { it('G2Element', () => { strictEqual(G2Element.SIZE, 96); - const pk = G1Element.from_bytes(getPkBytes()); - const sig = G2Element.from_bytes(getSignatureBytes()); + const pk = G1Element.fromBytes(getPkBytes()); + const sig = G2Element.fromBytes(getSignatureBytes()); const aggSig = AugSchemeMPL.aggregate([sig]); - const sig2 = G2Element.from_bytes(getSignatureBytes()); + const sig2 = G2Element.fromBytes(getSignatureBytes()); const isValid: boolean = AugSchemeMPL.verify(pk, getMessageBytes(), sig); const serialized: Uint8Array = sig.serialize(); diff --git a/src/dashbls/js_build_docker.sh b/src/dashbls/js_build_docker.sh new file mode 100755 index 0000000000..170254e7b6 --- /dev/null +++ b/src/dashbls/js_build_docker.sh @@ -0,0 +1,18 @@ +DOCKER_IMAGE=emscripten/emsdk + +git submodule update --init --recursive +mkdir js_build + +docker run \ + --rm \ + -v $(pwd):/src \ + -w="/src/js_build" \ + $DOCKER_IMAGE \ + emcmake cmake /src + +docker run \ + --rm \ + -v $(pwd):/src \ + -w="/src/js_build" \ + $DOCKER_IMAGE \ + cmake --build . -- -j10 diff --git a/src/dashbls/python-bindings/CMakeLists.txt b/src/dashbls/python-bindings/CMakeLists.txt index a49a5affd6..4e0db652b7 100644 --- a/src/dashbls/python-bindings/CMakeLists.txt +++ b/src/dashbls/python-bindings/CMakeLists.txt @@ -3,7 +3,7 @@ include(FetchContent) FetchContent_Declare( pybind11 GIT_REPOSITORY https://github.com/pybind/pybind11.git - GIT_TAG v2.9.1 + GIT_TAG v2.10.0 ) FetchContent_MakeAvailable(pybind11) diff --git a/src/dashbls/setup.py b/src/dashbls/setup.py index 4d2482b9da..7b4c0bfbbc 100644 --- a/src/dashbls/setup.py +++ b/src/dashbls/setup.py @@ -196,8 +196,8 @@ if platform.system() == "Windows": long_description_content_type="text/markdown", url="https://github.com/Chia-Network/bls-signatures", python_requires=">=3.7", - setup_requires=["pybind11>=2.5.0"], - install_requires=["pybind11>=2.5.0"], + setup_requires=["pybind11>=2.10.0"], + install_requires=["pybind11>=2.10.0"], ext_modules=ext_modules, cmdclass={"build_ext": BuildExt}, zip_safe=False, diff --git a/src/dashbls/src/bls.cpp b/src/dashbls/src/bls.cpp index c4bbec5d01..e0af3a3882 100644 --- a/src/dashbls/src/bls.cpp +++ b/src/dashbls/src/bls.cpp @@ -78,14 +78,16 @@ void BLS::SetSecureAllocator( } -void BLS::CheckRelicErrors() +void BLS::CheckRelicErrors(bool should_throw) { if (!core_get()) { throw std::runtime_error("Library not initialized properly. Call BLS::Init()"); } if (core_get()->code != RLC_OK) { core_get()->code = RLC_OK; - throw std::invalid_argument("Relic library error"); + if (should_throw) { + throw std::invalid_argument("Relic library error"); + } } } diff --git a/src/dashbls/src/elements.cpp b/src/dashbls/src/elements.cpp index 97f70123a1..d53426da02 100644 --- a/src/dashbls/src/elements.cpp +++ b/src/dashbls/src/elements.cpp @@ -82,9 +82,7 @@ G1Element G1Element::FromBytesUnchecked(Bytes const bytes, bool fLegacy) } } g1_read_bin(ele.p, buffer, G1Element::SIZE + 1); - if (!fLegacy) { - BLS::CheckRelicErrors(); - } + BLS::CheckRelicErrors(!fLegacy); return ele; } @@ -293,9 +291,7 @@ G2Element G2Element::FromBytesUnchecked(Bytes const bytes, const bool fLegacy) } g2_read_bin(ele.q, buffer, G2Element::SIZE + 1); - if (!fLegacy) { - BLS::CheckRelicErrors(); - } + BLS::CheckRelicErrors(!fLegacy); return ele; } From e0e86cffd564a37ae102a3b4a6654a7f098a775e Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Thu, 16 Mar 2023 18:28:38 +0200 Subject: [PATCH 28/63] fix: check HPMNs duplicate on tx broadcast (#5257) ## Issue being fixed or feature implemented Before this fix, uniqueness of HPMN `platformNodeID` was checked only while processing a block containing a `ProRegTx` or a `ProUpServTx`. This is not enough as a `ProRegTx` or `ProUpServTx` containing duplicate HPMN `platformNodeID` must be rejected at tx broadcast level. ## What was done? Checking uniqueness when calling respective RPC and when receiving such txs. ## How Has This Been Tested? ## Breaking Changes ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [x] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/evo/deterministicmns.cpp | 14 +++++++ test/functional/feature_dip3_v19.py | 19 ++++++++- test/functional/feature_llmq_hpmn.py | 23 +--------- .../test_framework/test_framework.py | 42 +++++++++++++++++-- 4 files changed, 71 insertions(+), 27 deletions(-) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index ef84168498..c057e1e7c9 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -1499,6 +1499,13 @@ bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValid return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, REJECT_DUPLICATE, "bad-protx-dup-key"); } + // never allow duplicate platformNodeIds for HPMNs + if (ptx.nType == MnType::HighPerformance) { + if (mnList.HasUniqueProperty(ptx.platformNodeID)) { + return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, REJECT_DUPLICATE, "bad-protx-dup-platformnodeid"); + } + } + if (!deterministicMNManager->IsDIP3Enforced(pindexPrev->nHeight)) { if (ptx.keyIDOwner != ptx.keyIDVoting) { return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, REJECT_INVALID, "bad-protx-key-not-same"); @@ -1564,6 +1571,13 @@ bool CheckProUpServTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVa return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, REJECT_DUPLICATE, "bad-protx-dup-addr"); } + // don't allow updating to platformNodeIds already used by other HPMNs + if (ptx.nType == MnType::HighPerformance) { + if (mnList.HasUniqueProperty(ptx.platformNodeID) && mnList.GetUniquePropertyMN(ptx.platformNodeID)->proTxHash != ptx.proTxHash) { + return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, REJECT_DUPLICATE, "bad-protx-dup-platformnodeid"); + } + } + if (ptx.scriptOperatorPayout != CScript()) { if (mn->nOperatorReward == 0) { // don't allow setting operator reward payee in case no operatorReward was set diff --git a/test/functional/feature_dip3_v19.py b/test/functional/feature_dip3_v19.py index 5b6839dc4a..a60b64901b 100755 --- a/test/functional/feature_dip3_v19.py +++ b/test/functional/feature_dip3_v19.py @@ -43,7 +43,7 @@ class TestP2PConn(P2PInterface): class DIP3V19Test(DashTestFramework): def set_test_params(self): - self.set_dash_test_params(6, 5, fast_dip3_enforcement=True) + self.set_dash_test_params(6, 5, fast_dip3_enforcement=True, hpmn_count=2) def run_test(self): # Connect all nodes to node1 so that we always have the whole network connected @@ -78,6 +78,23 @@ class DIP3V19Test(DashTestFramework): self.mine_cycle_quorum(llmq_type_name='llmq_test_dip0024', llmq_type=103) + hpmn_info_0 = self.dynamically_add_masternode(hpmn=True, rnd=7) + assert hpmn_info_0 is not None + self.nodes[0].generate(8) + self.sync_blocks(self.nodes) + + self.log.info("Checking that protxs with duplicate HPMN fields are rejected") + hpmn_info_1 = self.dynamically_add_masternode(hpmn=True, rnd=7, should_be_rejected=True) + assert hpmn_info_1 is None + self.dynamically_hpmn_update_service(hpmn_info_0, 8) + hpmn_info_2 = self.dynamically_add_masternode(hpmn=True, rnd=8, should_be_rejected=True) + assert hpmn_info_2 is None + hpmn_info_3 = self.dynamically_add_masternode(hpmn=True, rnd=9) + assert hpmn_info_3 is not None + self.nodes[0].generate(8) + self.sync_blocks(self.nodes) + self.dynamically_hpmn_update_service(hpmn_info_0, 9, should_be_rejected=True) + revoke_protx = self.mninfo[-1].proTxHash revoke_keyoperator = self.mninfo[-1].keyOperator self.log.info(f"Trying to revoke proTx:{revoke_protx}") diff --git a/test/functional/feature_llmq_hpmn.py b/test/functional/feature_llmq_hpmn.py index 86881f346d..7abc4d95ad 100755 --- a/test/functional/feature_llmq_hpmn.py +++ b/test/functional/feature_llmq_hpmn.py @@ -10,11 +10,9 @@ Checks HPMNs ''' from _decimal import Decimal -import random from io import BytesIO from test_framework.mininode import P2PInterface -from test_framework.script import hash160 from test_framework.messages import CBlock, CBlockHeader, CCbTx, CMerkleBlock, FromHex, hash256, msg_getmnlistd, \ QuorumId, ser_uint256 from test_framework.test_framework import DashTestFramework @@ -103,7 +101,7 @@ class LLMQHPMNTest(DashTestFramework): self.test_getmnlistdiff(null_hash, b_i, {}, [], expectedUpdated) self.test_masternode_count(expected_mns_count=4, expected_hpmns_count=i+1) - self.test_hpmn_update_service(hpmn_info) + self.dynamically_hpmn_update_service(hpmn_info) self.log.info("Test llmq_platform are formed only with HPMNs") for i in range(3): @@ -235,25 +233,6 @@ class LLMQHPMNTest(DashTestFramework): assert_equal(detailed_count['regular']['total'], expected_mns_count) assert_equal(detailed_count['hpmn']['total'], expected_hpmns_count) - def test_hpmn_update_service(self, hpmn_info): - funds_address = self.nodes[0].getnewaddress() - operator_reward_address = self.nodes[0].getnewaddress() - - # For the sake of the test, generate random nodeid, p2p and http platform values - rnd = random.randint(1000, 65000) - platform_node_id = hash160(b'%d' % rnd).hex() - platform_p2p_port = '%d' % (rnd + 1) - platform_http_port = '%d' % (rnd + 2) - - self.nodes[0].sendtoaddress(funds_address, 1) - self.nodes[0].generate(1) - self.sync_all(self.nodes) - - self.nodes[0].protx('update_service_hpmn', hpmn_info.proTxHash, hpmn_info.addr, hpmn_info.keyOperator, platform_node_id, platform_p2p_port, platform_http_port, operator_reward_address, funds_address) - self.nodes[0].generate(1) - self.sync_all(self.nodes) - self.log.info("Updated HPMN %s: platformNodeID=%s, platformP2PPort=%s, platformHTTPPort=%s" % (hpmn_info.proTxHash, platform_node_id, platform_p2p_port, platform_http_port)) - def test_getmnlistdiff(self, baseBlockHash, blockHash, baseMNList, expectedDeleted, expectedUpdated): d = self.test_getmnlistdiff_base(baseBlockHash, blockHash) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 8019bba959..dcdb12f5e1 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -1056,13 +1056,21 @@ class DashTestFramework(BitcoinTestFramework): for i in range(0, idx): self.connect_nodes(i, idx) - def dynamically_add_masternode(self, hpmn=False): + def dynamically_add_masternode(self, hpmn=False, rnd=None, should_be_rejected=False): mn_idx = len(self.nodes) node_p2p_port = p2p_port(mn_idx) node_rpc_port = rpc_port(mn_idx) - created_mn_info = self.dynamically_prepare_masternode(mn_idx, node_p2p_port, hpmn) + protx_success = False + try: + created_mn_info = self.dynamically_prepare_masternode(mn_idx, node_p2p_port, hpmn, rnd) + protx_success = True + except: + self.log.info("protx_hpmn rejected") + if should_be_rejected: + assert_equal(protx_success, False) + return self.dynamically_initialize_datadir(self.nodes[0].chain,node_p2p_port, node_rpc_port) node_info = self.add_dynamically_node(self.extra_args[1]) @@ -1084,7 +1092,7 @@ class DashTestFramework(BitcoinTestFramework): self.log.info("Successfully started and synced proTx:"+str(created_mn_info.proTxHash)) return created_mn_info - def dynamically_prepare_masternode(self, idx, node_p2p_port, hpmn=False): + def dynamically_prepare_masternode(self, idx, node_p2p_port, hpmn=False, rnd=None): bls = self.nodes[0].bls('generate') collateral_address = self.nodes[0].getnewaddress() funds_address = self.nodes[0].getnewaddress() @@ -1092,7 +1100,7 @@ class DashTestFramework(BitcoinTestFramework): voting_address = self.nodes[0].getnewaddress() reward_address = self.nodes[0].getnewaddress() - platform_node_id = hash160(b'%d' % node_p2p_port).hex() + platform_node_id = hash160(b'%d' % rnd).hex() if rnd is not None else hash160(b'%d' % node_p2p_port).hex() platform_p2p_port = '%d' % (node_p2p_port + 101) if hpmn else '' platform_http_port = '%d' % (node_p2p_port + 102) if hpmn else '' @@ -1126,6 +1134,32 @@ class DashTestFramework(BitcoinTestFramework): self.log.info("Prepared %s %d: collateral_txid=%s, collateral_vout=%d, protxHash=%s" % (mn_type_str, idx, collateral_txid, collateral_vout, protx_result)) return mn_info + def dynamically_hpmn_update_service(self, hpmn_info, rnd=None, should_be_rejected=False): + funds_address = self.nodes[0].getnewaddress() + operator_reward_address = self.nodes[0].getnewaddress() + + # For the sake of the test, generate random nodeid, p2p and http platform values + r = rnd if rnd is not None else random.randint(1000, 65000) + platform_node_id = hash160(b'%d' % r).hex() + platform_p2p_port = '%d' % (r + 1) + platform_http_port = '%d' % (r + 2) + + self.nodes[0].sendtoaddress(funds_address, 1) + self.nodes[0].generate(1) + self.sync_all(self.nodes) + + protx_success = False + try: + self.nodes[0].protx('update_service_hpmn', hpmn_info.proTxHash, hpmn_info.addr, hpmn_info.keyOperator, platform_node_id, platform_p2p_port, platform_http_port, operator_reward_address, funds_address) + self.nodes[0].generate(1) + self.sync_all(self.nodes) + self.log.info("Updated HPMN %s: platformNodeID=%s, platformP2PPort=%s, platformHTTPPort=%s" % (hpmn_info.proTxHash, platform_node_id, platform_p2p_port, platform_http_port)) + protx_success = True + except: + self.log.info("protx_hpmn rejected") + if should_be_rejected: + assert_equal(protx_success, False) + def prepare_masternodes(self): self.log.info("Preparing %d masternodes" % self.mn_count) rewardsAddr = self.nodes[0].getnewaddress() From 6f2e6f47eeee21c682c4502608756464dff437e2 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 16 Mar 2023 19:47:59 +0300 Subject: [PATCH 29/63] chore: Move logs about `nConsecutivePayments` under `MNPAYMENTS` debug category (#5251) ## Issue being fixed or feature implemented These messages are pretty annoying on reindex and shouldn't really be shown in logs unless you actually need to debug mn payments. ## What was done? move messages under `MNPAYMENTS` debug category ## How Has This Been Tested? reindex ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/evo/deterministicmns.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index c057e1e7c9..04206d15ba 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -1002,14 +1002,14 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C if (dmn->nType == MnType::HighPerformance) { ++newState->nConsecutivePayments; if (debugLogs) { - LogPrintf("CDeterministicMNManager::%s -- MN %s is a HPMN, bumping nConsecutivePayments to %d\n", + LogPrint(BCLog::MNPAYMENTS, "CDeterministicMNManager::%s -- MN %s is a HPMN, bumping nConsecutivePayments to %d\n", __func__, dmn->proTxHash.ToString(), newState->nConsecutivePayments); } } newList.UpdateMN(payee->proTxHash, newState); if (debugLogs) { dmn = newList.GetMN(payee->proTxHash); - LogPrintf("CDeterministicMNManager::%s -- MN %s, nConsecutivePayments=%d\n", + LogPrint(BCLog::MNPAYMENTS, "CDeterministicMNManager::%s -- MN %s, nConsecutivePayments=%d\n", __func__, dmn->proTxHash.ToString(), dmn->pdmnState->nConsecutivePayments); } } @@ -1021,7 +1021,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C if (dmn.nType != MnType::HighPerformance) return; if (dmn.pdmnState->nConsecutivePayments == 0) return; if (debugLogs) { - LogPrintf("CDeterministicMNManager::%s -- MN %s, reset nConsecutivePayments %d->0\n", + LogPrint(BCLog::MNPAYMENTS, "CDeterministicMNManager::%s -- MN %s, reset nConsecutivePayments %d->0\n", __func__, dmn.proTxHash.ToString(), dmn.pdmnState->nConsecutivePayments); } auto newState = std::make_shared(*dmn.pdmnState); From e0fe6e49e0ee52b4cdca10d52fccf69331de9eef Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Mon, 20 Mar 2023 18:20:29 +0200 Subject: [PATCH 30/63] chore: bump version to rc.7 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 3def30d01b..857ff1b627 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 19) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 6) +define(_CLIENT_VERSION_RC, 7) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2023) define(_COPYRIGHT_HOLDERS,[The %s developers]) From 020070e48b8ecbb0c6476a9caf141a7264baf543 Mon Sep 17 00:00:00 2001 From: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> Date: Thu, 23 Mar 2023 09:52:09 -0500 Subject: [PATCH 31/63] fix: hpmn registration after revocation caused mining failure (#5265) ## Issue being fixed or feature implemented We reset operator info on revocation; but then on replacement via new register we try to "RemoveMN", which tries to remove platformNodeID but that's already been cleared ## What was done? Only try to delete platformNodeID if it's non-null ## How Has This Been Tested? Mined with it on testnet; mining works ## Breaking Changes This will fork off other testnet nodes, as this fixes the logic ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --------- Co-authored-by: Odysseas Gabrielides --- src/evo/deterministicmns.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 04206d15ba..9905d351b5 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -514,7 +514,7 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn, bool fBumpTota } if (dmn->nType == MnType::HighPerformance) { - if (!AddUniqueProperty(*dmn, dmn->pdmnState->platformNodeID)) { + if (dmn->pdmnState->platformNodeID != uint160() && !AddUniqueProperty(*dmn, dmn->pdmnState->platformNodeID)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; throw(std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate platformNodeID=%s", __func__, dmn->proTxHash.ToString(), dmn->pdmnState->platformNodeID.ToString()))); @@ -615,7 +615,7 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash) } if (dmn->nType == MnType::HighPerformance) { - if (!DeleteUniqueProperty(*dmn, dmn->pdmnState->platformNodeID)) { + if (dmn->pdmnState->platformNodeID != uint160() && !DeleteUniqueProperty(*dmn, dmn->pdmnState->platformNodeID)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; throw(std::runtime_error(strprintf("%s: Can't delete a masternode %s with a duplicate platformNodeID=%s", __func__, dmn->proTxHash.ToString(), dmn->pdmnState->platformNodeID.ToString()))); From 5214459ffb863d31571cbcef211930e6873d9e9d Mon Sep 17 00:00:00 2001 From: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> Date: Thu, 23 Mar 2023 09:51:05 -0500 Subject: [PATCH 32/63] ci: resolve gitian automation failures on dashevo repo (#5267) ## Issue being fixed or feature implemented Automation in private dashevo GitHub was failing due to the branch trying to be built not having the automation be the newer tagged based system. as such, if you simply tag a commit from the dashpay repo and try to build it using automation, the build would fail. This should resolve the issue. Recommended to BP so that we don't have this issue when building v19.x branch builds ## What was done? ## How Has This Been Tested? Creating a docker image should now be as simple pushing a branch and tag to dashevo/dash; start the automation on branch develop with tag previously specified ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- contrib/containers/deploy/Dockerfile.GitHubActions.Gitian | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/containers/deploy/Dockerfile.GitHubActions.Gitian b/contrib/containers/deploy/Dockerfile.GitHubActions.Gitian index 6581a4f269..cafabd00e0 100644 --- a/contrib/containers/deploy/Dockerfile.GitHubActions.Gitian +++ b/contrib/containers/deploy/Dockerfile.GitHubActions.Gitian @@ -5,7 +5,7 @@ LABEL description="Dockerised DashCore" ARG USER_ID ARG GROUP_ID -ARG BRANCH +ARG TAG ENV HOME /home/dash @@ -23,7 +23,7 @@ RUN apt-get update && \ ca-certificates \ && rm -rf /var/lib/apt/lists/* -COPY dashcore-binaries/${BRANCH}/dashcore* /home/dash +COPY dashcore-binaries/${TAG}/dashcore* /home/dash RUN mach=$(uname -m) \ && case $mach in aarch64) arch="aarch64-linux-gnu"; ;; x86_64) arch="x86_64-linux-gnu"; ;; *) echo "ERROR: Machine type $mach not supported."; ;; esac \ From 6fb6311b7dce6da85c6ddaf153ed778a3448b37b Mon Sep 17 00:00:00 2001 From: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> Date: Thu, 23 Mar 2023 10:04:44 -0500 Subject: [PATCH 33/63] Merge pull request #5249 from knst/qt-create-wallet-fix backport: bitcoin-core/gui#171 --- src/qt/forms/createwalletdialog.ui | 210 ++++++++++++++++------------- 1 file changed, 115 insertions(+), 95 deletions(-) diff --git a/src/qt/forms/createwalletdialog.ui b/src/qt/forms/createwalletdialog.ui index 1de5f937a9..7002d1f6f0 100644 --- a/src/qt/forms/createwalletdialog.ui +++ b/src/qt/forms/createwalletdialog.ui @@ -6,106 +6,126 @@ 0 0 - 364 - 195 + 407 + 0 Create Wallet - - - - 10 - 140 - 341 - 40 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 120 - 20 - 231 - 24 - - - - - - - 20 - 20 - 101 - 21 - - - - Wallet Name - - - - - - 20 - 60 - 171 - 22 - - - - Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice. - - - Encrypt Wallet - - - true - - - - - false - - - - 20 - 90 - 171 - 22 - - - - Disable private keys for this wallet. Wallets with private keys disabled will have no private keys and cannot have an HD seed or imported private keys. This is ideal for watch-only wallets. - - - Disable Private Keys - - - - - - 20 - 120 - 171 - 22 - - - - Make a blank wallet. Blank wallets do not initially have private keys or scripts. Private keys and addresses can be imported, or an HD seed can be set, at a later time. - - - Make Blank Wallet - - + + true + + + + + + + + Wallet Name + + + + + + + + 262 + 0 + + + + Wallet + + + + + + + + + Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice. + + + Encrypt Wallet + + + false + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 8 + + + + + + + + Advanced Options + + + + + + true + + + Disable private keys for this wallet. Wallets with private keys disabled will have no private keys and cannot have an HD seed or imported private keys. This is ideal for watch-only wallets. + + + Disable Private Keys + + + + + + + Make a blank wallet. Blank wallets do not initially have private keys or scripts. Private keys and addresses can be imported, or an HD seed can be set, at a later time. + + + Make Blank Wallet + + + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + wallet_name_line_edit From 9b98d5f90b1d3466fe037b7e6cbcdd5919cde50d Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 23 Mar 2023 18:06:06 +0300 Subject: [PATCH 34/63] fix(governance): Do not keep triggers longer than nSuperblockCycle (#5268) ## Issue being fixed or feature implemented Keeping too many triggers on testnet and syncing them can result in p2p bans because some of these triggers might be invalid already. Limiting their lifetime should help. ## What was done? ## How Has This Been Tested? ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/governance/classes.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/governance/classes.cpp b/src/governance/classes.cpp index 0f85d70c23..eb0b75c4ee 100644 --- a/src/governance/classes.cpp +++ b/src/governance/classes.cpp @@ -677,17 +677,18 @@ bool CSuperblock::IsValid(const CTransaction& txNew, int nBlockHeight, CAmount b bool CSuperblock::IsExpired(const CGovernanceManager& governanceManager) const { int nExpirationBlocks; - // Executed triggers are kept for another superblock cycle (approximately 1 month), - // other valid triggers are kept for ~1 day only, everything else is pruned after ~1h. + // Executed triggers are kept for another superblock cycle (approximately 1 month for mainnet). + // Other valid triggers are kept for ~1 day only (for mainnet, but no longer than a superblock cycle for other networks). + // Everything else is pruned after ~1h (for mainnet, but no longer than a superblock cycle for other networks). switch (nStatus) { case SEEN_OBJECT_EXECUTED: nExpirationBlocks = Params().GetConsensus().nSuperblockCycle; break; case SEEN_OBJECT_IS_VALID: - nExpirationBlocks = 576; + nExpirationBlocks = std::min(576, Params().GetConsensus().nSuperblockCycle); break; default: - nExpirationBlocks = 24; + nExpirationBlocks = std::min(24, Params().GetConsensus().nSuperblockCycle); break; } From 5abc5c5f34d616349106a98863ad1838f71ef6a6 Mon Sep 17 00:00:00 2001 From: pasta Date: Wed, 22 Mar 2023 19:52:43 -0500 Subject: [PATCH 35/63] chore: bump version to rc.8 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 857ff1b627..f5f75eafd4 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 19) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 7) +define(_CLIENT_VERSION_RC, 8) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2023) define(_COPYRIGHT_HOLDERS,[The %s developers]) From 38c1ee7509696bbef0bb07d0463ded155b2330e6 Mon Sep 17 00:00:00 2001 From: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> Date: Wed, 29 Mar 2023 07:32:24 -0500 Subject: [PATCH 36/63] log: add a log for invalid mnauth (#5271) ## Issue being fixed or feature implemented We are seeing lots of "invalid mnauth" on testnet.. We should be logging this anyhow ## What was done? Add some logging the the mnauth sig isn't valid ## How Has This Been Tested? make check ## Breaking Changes None ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/evo/mnauth.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/evo/mnauth.cpp b/src/evo/mnauth.cpp index 252b1390c8..c0ef483c21 100644 --- a/src/evo/mnauth.cpp +++ b/src/evo/mnauth.cpp @@ -91,6 +91,7 @@ void CMNAuth::ProcessMessage(CNode& peer, CConnman& connman, std::string_view ms if (!mnauth.sig.IsValid()) { LOCK(cs_main); Misbehaving(peer.GetId(), 100, "invalid mnauth signature"); + LogPrint(BCLog::NET_NETCONN, "CMNAuth::ProcessMessage -- invalid mnauth for protx=%s with sig=%s\n", mnauth.proRegTxHash.ToString(), mnauth.sig.ToString()); return; } From bcb65a217df4e5e5a59834621a7e7002c15519af Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Thu, 30 Mar 2023 18:05:15 +0300 Subject: [PATCH 37/63] fix(net): Do not punish nodes when Quorum data are missing. (#5272) ## Issue being fixed or feature implemented Currently, we store internally the nodes that already requested `QGETDATA` for the same Quorum. If data for the same Quorum is requested twice from the same `proRegTx`, then the requester is P2P misbehaved. ## What was done? Some data like `VerificationVector` and `EncryptedContributions` are not instantly available. This PR does not misbehave nodes for requesting data that weren't available when asked. ## How Has This Been Tested? ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/llmq/quorums.cpp | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 3d91777e0e..73fb3a751e 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -630,13 +630,29 @@ void CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, C CQuorumDataRequest request; vRecv >> request; - auto sendQDATA = [&](CQuorumDataRequest::Errors nError = CQuorumDataRequest::Errors::UNDEFINED, + auto sendQDATA = [&](CQuorumDataRequest::Errors nError, + bool request_limit_exceeded, const CDataStream& body = CDataStream(SER_NETWORK, PROTOCOL_VERSION)) { + switch (nError) { + case (CQuorumDataRequest::Errors::NONE): + case (CQuorumDataRequest::Errors::QUORUM_TYPE_INVALID): + case (CQuorumDataRequest::Errors::QUORUM_BLOCK_NOT_FOUND): + case (CQuorumDataRequest::Errors::QUORUM_NOT_FOUND): + case (CQuorumDataRequest::Errors::MASTERNODE_IS_NO_MEMBER): + case (CQuorumDataRequest::Errors::UNDEFINED): + if (request_limit_exceeded) errorHandler("Request limit exceeded", 25); + break; + case (CQuorumDataRequest::Errors::QUORUM_VERIFICATION_VECTOR_MISSING): + case (CQuorumDataRequest::Errors::ENCRYPTED_CONTRIBUTIONS_MISSING): + // Do not punish limit exceed if we don't have the requested data + break; + } request.SetError(nError); CDataStream ssResponse(SER_NETWORK, pfrom.GetSendVersion(), request, body); connman.PushMessage(&pfrom, CNetMsgMaker(pfrom.GetSendVersion()).Make(NetMsgType::QDATA, ssResponse)); }; + bool request_limit_exceeded(false); { LOCK2(cs_main, cs_data_requests); CQuorumDataRequestKey key; @@ -650,24 +666,24 @@ void CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, C } else if (it->second.IsExpired()) { it->second = request; } else { - errorHandler("Request limit exceeded", 25); + request_limit_exceeded = true; } } if (!GetLLMQParams(request.GetLLMQType()).has_value()) { - sendQDATA(CQuorumDataRequest::Errors::QUORUM_TYPE_INVALID); + sendQDATA(CQuorumDataRequest::Errors::QUORUM_TYPE_INVALID, request_limit_exceeded); return; } const CBlockIndex* pQuorumBaseBlockIndex = WITH_LOCK(cs_main, return LookupBlockIndex(request.GetQuorumHash())); if (pQuorumBaseBlockIndex == nullptr) { - sendQDATA(CQuorumDataRequest::Errors::QUORUM_BLOCK_NOT_FOUND); + sendQDATA(CQuorumDataRequest::Errors::QUORUM_BLOCK_NOT_FOUND, request_limit_exceeded); return; } const CQuorumCPtr pQuorum = GetQuorum(request.GetLLMQType(), pQuorumBaseBlockIndex); if (pQuorum == nullptr) { - sendQDATA(CQuorumDataRequest::Errors::QUORUM_NOT_FOUND); + sendQDATA(CQuorumDataRequest::Errors::QUORUM_NOT_FOUND, request_limit_exceeded); return; } @@ -676,7 +692,7 @@ void CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, C // Check if request wants QUORUM_VERIFICATION_VECTOR data if (request.GetDataMask() & CQuorumDataRequest::QUORUM_VERIFICATION_VECTOR) { if (!pQuorum->HasVerificationVector()) { - sendQDATA(CQuorumDataRequest::Errors::QUORUM_VERIFICATION_VECTOR_MISSING); + sendQDATA(CQuorumDataRequest::Errors::QUORUM_VERIFICATION_VECTOR_MISSING, request_limit_exceeded); return; } @@ -688,20 +704,20 @@ void CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, C int memberIdx = pQuorum->GetMemberIndex(request.GetProTxHash()); if (memberIdx == -1) { - sendQDATA(CQuorumDataRequest::Errors::MASTERNODE_IS_NO_MEMBER); + sendQDATA(CQuorumDataRequest::Errors::MASTERNODE_IS_NO_MEMBER, request_limit_exceeded); return; } std::vector> vecEncrypted; if (!dkgManager.GetEncryptedContributions(request.GetLLMQType(), pQuorumBaseBlockIndex, pQuorum->qc->validMembers, request.GetProTxHash(), vecEncrypted)) { - sendQDATA(CQuorumDataRequest::Errors::ENCRYPTED_CONTRIBUTIONS_MISSING); + sendQDATA(CQuorumDataRequest::Errors::ENCRYPTED_CONTRIBUTIONS_MISSING, request_limit_exceeded); return; } ssResponseData << vecEncrypted; } - sendQDATA(CQuorumDataRequest::Errors::NONE, ssResponseData); + sendQDATA(CQuorumDataRequest::Errors::NONE, request_limit_exceeded, ssResponseData); return; } From 80ebf4761814db641ca21b9a618be8ea2bffa721 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Wed, 29 Mar 2023 19:23:45 +0300 Subject: [PATCH 38/63] feat(rpc): Added RPC cleardiscouraged (#5273) ## Issue being fixed or feature implemented ## What was done? Added RPC `cleardiscouraged` which clears internally the list of discouraged peers. Note: Implementation of a `listdiscouraged` RPC is not possible because the internal data structure used for discouraged peers is a Bloom filter. ## How Has This Been Tested? ## Breaking Changes ## 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 - [x] I have made corresponding changes to the documentation **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- doc/release-notes-5273.md | 5 +++++ src/banman.cpp | 10 ++++++++++ src/banman.h | 1 + src/rpc/net.cpp | 22 ++++++++++++++++++++++ 4 files changed, 38 insertions(+) create mode 100644 doc/release-notes-5273.md diff --git a/doc/release-notes-5273.md b/doc/release-notes-5273.md new file mode 100644 index 0000000000..16bd0c88dc --- /dev/null +++ b/doc/release-notes-5273.md @@ -0,0 +1,5 @@ +Added RPCs +-------- + +- `cleardiscouraged` clears all the already discouraged peers. + diff --git a/src/banman.cpp b/src/banman.cpp index 48973e9c4a..807ad19faa 100644 --- a/src/banman.cpp +++ b/src/banman.cpp @@ -68,6 +68,16 @@ void BanMan::ClearBanned() if (m_client_interface) m_client_interface->BannedListChanged(); } +void BanMan::ClearDiscouraged() +{ + { + LOCK(m_cs_banned); + m_discouraged.reset(); + m_is_dirty = true; + } + if (m_client_interface) m_client_interface->BannedListChanged(); +} + bool BanMan::IsDiscouraged(const CNetAddr& net_addr) { LOCK(m_cs_banned); diff --git a/src/banman.h b/src/banman.h index 6b972c84e2..ca46677e3e 100644 --- a/src/banman.h +++ b/src/banman.h @@ -63,6 +63,7 @@ public: void Ban(const CSubNet& sub_net, int64_t ban_time_offset = 0, bool since_unix_epoch = false); void Discourage(const CNetAddr& net_addr); void ClearBanned(); + void ClearDiscouraged(); //! Return whether net_addr is banned bool IsBanned(const CNetAddr& net_addr); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index eca3d2179c..8db4721c19 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -736,6 +736,27 @@ static UniValue clearbanned(const JSONRPCRequest& request) return NullUniValue; } +static UniValue cleardiscouraged(const JSONRPCRequest& request) +{ + RPCHelpMan{"cleardiscouraged", + "\nClear all discouraged nodes.\n", + {}, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + HelpExampleCli("cleardiscouraged", "") + + HelpExampleRpc("cleardiscouraged", "") + }, + }.Check(request); + NodeContext& node = EnsureNodeContext(request.context); + if (!node.banman) { + throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded"); + } + + node.banman->ClearDiscouraged(); + + return NullUniValue; +} + static UniValue setnetworkactive(const JSONRPCRequest& request) { RPCHelpMan{"setnetworkactive", @@ -825,6 +846,7 @@ static const CRPCCommand commands[] = { "network", "setban", &setban, {"subnet", "command", "bantime", "absolute"} }, { "network", "listbanned", &listbanned, {} }, { "network", "clearbanned", &clearbanned, {} }, + { "network", "cleardiscouraged", &cleardiscouraged, {} }, { "network", "setnetworkactive", &setnetworkactive, {"state"} }, { "network", "getnodeaddresses", &getnodeaddresses, {"count"} }, }; From 5bffe3fdae5bf20e58d9bf890b342659efac3857 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Thu, 30 Mar 2023 18:06:47 +0300 Subject: [PATCH 39/63] fix: hpmn adjustements to getprojectedmnpayees (#5274) ## Issue being fixed or feature implemented `GetProjectedMNPayees` wasn't projecting MN payees correctly. ## What was done? HPMNs are now added 4 times before sorting the return list. In addition, the case of last payee being HPMN and having still pending payments is handled. ## How Has This Been Tested? Tested on Masternodes / Next Payment tab on Qt client on Testnet. ## Breaking Changes ## Checklist: - [x] I have performed a self-review of my own code - [x] 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/evo/deterministicmns.cpp | 26 +++++++++++++++++++++++--- src/evo/deterministicmns.h | 9 +++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 9905d351b5..fe266149ad 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -218,15 +218,35 @@ std::vector CDeterministicMNList::GetProjectedMNPayees(int if (nCount < 0 ) { return {}; } - nCount = std::min(nCount, int(GetValidMNsCount())); + nCount = std::min(nCount, int(GetValidWeightedMNsCount())); std::vector result; result.reserve(nCount); + auto remaining_hpmn_payments = 0; + CDeterministicMNCPtr hpmn_to_be_skipped = nullptr; ForEachMNShared(true, [&](const CDeterministicMNCPtr& dmn) { - result.emplace_back(dmn); + if (dmn->pdmnState->nLastPaidHeight == nHeight) { + // We found the last MN Payee. + // If the last payee is a HPMN, we need to check its consecutive payments and pay him again if needed + if (dmn->nType == MnType::HighPerformance && dmn->pdmnState->nConsecutivePayments < dmn_types::HighPerformance.voting_weight) { + remaining_hpmn_payments = dmn_types::HighPerformance.voting_weight - dmn->pdmnState->nConsecutivePayments; + for ([[maybe_unused]] auto _ : irange::range(remaining_hpmn_payments)) { + result.emplace_back(dmn); + hpmn_to_be_skipped = dmn; + } + } + } + return; }); - std::sort(result.begin(), result.end(), [&](const CDeterministicMNCPtr& a, const CDeterministicMNCPtr& b) { + + ForEachMNShared(true, [&](const CDeterministicMNCPtr& dmn) { + if (dmn == hpmn_to_be_skipped) return; + for ([[maybe_unused]] auto _ : irange::range(GetMnType(dmn->nType).voting_weight)) { + result.emplace_back(dmn); + } + }); + std::sort(result.begin() + remaining_hpmn_payments, result.end(), [&](const CDeterministicMNCPtr& a, const CDeterministicMNCPtr& b) { return CompareByLastPaid(a.get(), b.get()); }); diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index bd7f74d15f..108cbbc75f 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -19,6 +19,7 @@ #include +#include #include #include @@ -241,6 +242,14 @@ public: return ranges::count_if(mnMap, [](const auto& p) { return p.second->nType == MnType::HighPerformance && IsMNValid(*p.second); }); } + [[nodiscard]] size_t GetValidWeightedMNsCount() const + { + return std::accumulate(mnMap.begin(), mnMap.end(), 0, [](auto res, const auto& p) { + if (!IsMNValid(*p.second)) return res; + return res + GetMnType(p.second->nType).voting_weight; + }); + } + /** * Execute a callback on all masternodes in the mnList. This will pass a reference * of each masternode to the callback function. This should be preferred over ForEachMNShared. From 8b21e2dbe98e3169d657e6239fc6e933f2f12a52 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Wed, 29 Mar 2023 15:34:19 +0300 Subject: [PATCH 40/63] log: Add logs when send qgetdata (#5275) ## Issue being fixed or feature implemented ## What was done? Added logs with requested parameters (`llmqType`, `quorumHash`, `proRegTx`) when sending `qgetdata` for better troubleshooting. ## How Has This Been Tested? ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/llmq/quorums.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 73fb3a751e..42af4ffd63 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -478,6 +478,8 @@ bool CQuorumManager::RequestQuorumData(CNode* pfrom, Consensus::LLMQType llmqTyp LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- Already requested\n", __func__); return false; } + LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- sending QGETDATA quorumHash[%s] llmqType[%d] proRegTx[%s]\n", __func__, key.quorumHash.ToString(), + ToUnderlying(key.llmqType), key.proRegTx.ToString()); CNetMsgMaker msgMaker(pfrom->GetSendVersion()); connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::QGETDATA, it.first->second)); From 1352362fc617ebfc7eedbf3ef9f3ab15295cc4d5 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 30 Mar 2023 19:45:02 +0300 Subject: [PATCH 41/63] fix(test): bump `quorum_data_request_expiration_timeout` to fix `p2p_quorum_data.py` (#5281) ## Issue being fixed or feature implemented fix `p2p_quorum_data.py` test broken by #5276 ## What was done? adjust data request expiration timeout in tests ## How Has This Been Tested? `./test/functional/test_runner.py p2p_quorum_data.py` ## 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 - [x] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- test/functional/test_framework/test_framework.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index dcdb12f5e1..04a6c34b6b 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -980,8 +980,8 @@ class DashTestFramework(BitcoinTestFramework): # This is nRequestTimeout in dash-q-recovery thread self.quorum_data_thread_request_timeout_seconds = 10 - # This is EXPIRATION_TIMEOUT in CQuorumDataRequest - self.quorum_data_request_expiration_timeout = 300 + # This is EXPIRATION_TIMEOUT + EXPIRATION_BIAS in CQuorumDataRequest + self.quorum_data_request_expiration_timeout = 360 def set_dash_dip8_activation(self, activate_after_block): self.dip8_activation_height = activate_after_block From ed71c6d652db0566931579eb65c9336ae219839a Mon Sep 17 00:00:00 2001 From: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> Date: Thu, 30 Mar 2023 10:24:44 -0500 Subject: [PATCH 42/63] fix: add a `bias` to IsExpired to avoid potential timing issues where nodeA thinks it's been 300 seconds but nodeB only thinks it's been 295 for some reason (#5276) ## Issue being fixed or feature implemented add a bias to IsExpired to avoid potential timing issues where nodeA thinks it's been 300 seconds but nodeB only thinks it's been 295 for some reason ## What was done? ## How Has This Been Tested? ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/llmq/quorums.cpp | 8 ++++---- src/llmq/quorums.h | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 42af4ffd63..cb4190863a 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -283,7 +283,7 @@ void CQuorumManager::UpdatedBlockTip(const CBlockIndex* pindexNew, bool fInitial LOCK(cs_data_requests); auto it = mapQuorumDataRequests.begin(); while (it != mapQuorumDataRequests.end()) { - if (it->second.IsExpired()) { + if (it->second.IsExpired(/*add_bias=*/true)) { it = mapQuorumDataRequests.erase(it); } else { ++it; @@ -474,7 +474,7 @@ bool CQuorumManager::RequestQuorumData(CNode* pfrom, Consensus::LLMQType llmqTyp key.quorumHash = pQuorumBaseBlockIndex->GetBlockHash(); key.llmqType = llmqType; auto it = mapQuorumDataRequests.emplace(key, CQuorumDataRequest(llmqType, pQuorumBaseBlockIndex->GetBlockHash(), nDataMask, proTxHash)); - if (!it.second && !it.first->second.IsExpired()) { + if (!it.second && !it.first->second.IsExpired(/*add_bias=*/true)) { LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- Already requested\n", __func__); return false; } @@ -665,7 +665,7 @@ void CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, C auto it = mapQuorumDataRequests.find(key); if (it == mapQuorumDataRequests.end()) { it = mapQuorumDataRequests.emplace(key, request).first; - } else if (it->second.IsExpired()) { + } else if (it->second.IsExpired(/*add_bias=*/false)) { it->second = request; } else { request_limit_exceeded = true; @@ -920,7 +920,7 @@ void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, co key.quorumHash = pQuorum->qc->quorumHash; key.llmqType = pQuorum->qc->llmqType; auto it = mapQuorumDataRequests.find(key); - if (it != mapQuorumDataRequests.end() && !it->second.IsExpired()) { + if (it != mapQuorumDataRequests.end() && !it->second.IsExpired(/*add_bias=*/true)) { printLog("Already asked"); continue; } diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index 5e6d12dd8c..6e24d369d1 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -83,6 +83,7 @@ private: bool fProcessed{false}; static constexpr int64_t EXPIRATION_TIMEOUT{300}; + static constexpr int64_t EXPIRATION_BIAS{60}; public: @@ -119,7 +120,7 @@ public: Errors GetError() const { return nError; } std::string GetErrorString() const; - bool IsExpired() const { return (GetTime() - nTime) >= EXPIRATION_TIMEOUT; } + bool IsExpired(bool add_bias) const { return (GetTime() - nTime) >= (EXPIRATION_TIMEOUT + (add_bias ? EXPIRATION_BIAS : 0)); } bool IsProcessed() const { return fProcessed; } void SetProcessed() { fProcessed = true; } From cb7c1f82937b5636784af0cea38988ba39d84524 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Thu, 30 Mar 2023 21:49:22 +0700 Subject: [PATCH 43/63] fix: add a missing name for key `hdaccounts` for RPC help for `getwalletinfo` (#5280) ## Issue being fixed or feature implemented RPC help has a wrongly generated RPC help output in CLI and online help: https://dashcore.readme.io/docs/core-api-ref-remote-procedure-calls-wallet#getwalletinfo New version: ``` ... "hdaccounts" : [ (json array) { (json object) "hdaccountindex" : n, (numeric) the index of the account "hdexternalkeyindex" : n, (numeric) current external childkey index "hdinternalkeyindex" : n (numeric) current internal childkey index }, ... ], ... ``` against old version: ``` ... "" : [ (json array) { (json object) "hdaccountindex" : n, (numeric) the index of the account "hdexternalkeyindex" : n, (numeric) current external childkey index "hdinternalkeyindex" : n (numeric) current internal childkey index }, ... ], ... ``` ## What was done? Add a missing name `hdaccounts` for that key for `getwalletinfo` RPC ## How Has This Been Tested? Run a command `help getwalletinfo` for old and for new versions. ## Breaking Changes No breaking changes. It doesn't change rpc, only change text description (help). ## Checklist: - [x] I have performed a self-review of my own code - [x] I have assigned this pull request to a milestone --- src/wallet/rpcwallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5118f7401f..3e1388da25 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2482,7 +2482,7 @@ static UniValue getwalletinfo(const JSONRPCRequest& request) {RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB"}, {RPCResult::Type::STR_HEX, "hdchainid", "the ID of the HD chain"}, {RPCResult::Type::STR, "hdaccountcount", "how many accounts of the HD chain are in this wallet"}, - {RPCResult::Type::ARR, "", "", + {RPCResult::Type::ARR, "hdaccounts", "", { {RPCResult::Type::OBJ, "", "", { From 26873b07c540c4560c3fa1fe3e6ed847958c3547 Mon Sep 17 00:00:00 2001 From: pasta Date: Thu, 30 Mar 2023 11:48:26 -0500 Subject: [PATCH 44/63] chore: bump version to rc.9 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index f5f75eafd4..91031f8156 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 19) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 8) +define(_CLIENT_VERSION_RC, 9) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2023) define(_COPYRIGHT_HOLDERS,[The %s developers]) From dfd091e5bce504adae740c1749d94f02e8b558b6 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 4 Apr 2023 19:07:00 +0300 Subject: [PATCH 45/63] refactor/fix: replace expired requests with a new one in RequestQuorumData (#5286) ## Issue being fixed or feature implemented should fix "qdata: Already received" discouraging issue the root of the issue is that we remove expired requests on UpdatedBlockTip which is too late sometimes. ## What was done? replacing expired requests with a new one in RequestQuorumData kind of does the same (drops the expired request) but without waiting for UpdatedBlockTip ## How Has This Been Tested? ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [ ] I have assigned this pull request to a milestone --- src/llmq/quorums.cpp | 45 +++++++++++++++----------------------------- src/llmq/quorums.h | 14 ++++++++++---- 2 files changed, 25 insertions(+), 34 deletions(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index cb4190863a..f771e54712 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -468,21 +468,22 @@ bool CQuorumManager::RequestQuorumData(CNode* pfrom, Consensus::LLMQType llmqTyp } LOCK(cs_data_requests); - CQuorumDataRequestKey key; - key.proRegTx = pfrom->GetVerifiedProRegTxHash(); - key.flag = true; - key.quorumHash = pQuorumBaseBlockIndex->GetBlockHash(); - key.llmqType = llmqType; - auto it = mapQuorumDataRequests.emplace(key, CQuorumDataRequest(llmqType, pQuorumBaseBlockIndex->GetBlockHash(), nDataMask, proTxHash)); - if (!it.second && !it.first->second.IsExpired(/*add_bias=*/true)) { - LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- Already requested\n", __func__); - return false; + const CQuorumDataRequestKey key(pfrom->GetVerifiedProRegTxHash(), true, pQuorumBaseBlockIndex->GetBlockHash(), llmqType); + const CQuorumDataRequest request(llmqType, pQuorumBaseBlockIndex->GetBlockHash(), nDataMask, proTxHash); + auto [old_pair, exists] = mapQuorumDataRequests.emplace(key, request); + if (!exists) { + if (old_pair->second.IsExpired(/*add_bias=*/true)) { + old_pair->second = request; + } else { + LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- Already requested\n", __func__); + return false; + } } LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- sending QGETDATA quorumHash[%s] llmqType[%d] proRegTx[%s]\n", __func__, key.quorumHash.ToString(), ToUnderlying(key.llmqType), key.proRegTx.ToString()); CNetMsgMaker msgMaker(pfrom->GetSendVersion()); - connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::QGETDATA, it.first->second)); + connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::QGETDATA, request)); return true; } @@ -657,11 +658,7 @@ void CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, C bool request_limit_exceeded(false); { LOCK2(cs_main, cs_data_requests); - CQuorumDataRequestKey key; - key.proRegTx = pfrom.GetVerifiedProRegTxHash(); - key.flag = false; - key.quorumHash = request.GetQuorumHash(); - key.llmqType = request.GetLLMQType(); + const CQuorumDataRequestKey key(pfrom.GetVerifiedProRegTxHash(), false, request.GetQuorumHash(), request.GetLLMQType()); auto it = mapQuorumDataRequests.find(key); if (it == mapQuorumDataRequests.end()) { it = mapQuorumDataRequests.emplace(key, request).first; @@ -734,11 +731,7 @@ void CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, C { LOCK2(cs_main, cs_data_requests); - CQuorumDataRequestKey key; - key.proRegTx = pfrom.GetVerifiedProRegTxHash(); - key.flag = true; - key.quorumHash = request.GetQuorumHash(); - key.llmqType = request.GetLLMQType(); + const CQuorumDataRequestKey key(pfrom.GetVerifiedProRegTxHash(), true, request.GetQuorumHash(), request.GetLLMQType()); auto it = mapQuorumDataRequests.find(key); if (it == mapQuorumDataRequests.end()) { errorHandler("Not requested"); @@ -914,11 +907,7 @@ void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, co pCurrentMemberHash = &vecMemberHashes[(nMyStartOffset + nTries++) % vecMemberHashes.size()]; { LOCK(cs_data_requests); - CQuorumDataRequestKey key; - key.proRegTx = *pCurrentMemberHash; - key.flag = true; - key.quorumHash = pQuorum->qc->quorumHash; - key.llmqType = pQuorum->qc->llmqType; + const CQuorumDataRequestKey key(*pCurrentMemberHash, true, pQuorum->qc->quorumHash, pQuorum->qc->llmqType); auto it = mapQuorumDataRequests.find(key); if (it != mapQuorumDataRequests.end() && !it->second.IsExpired(/*add_bias=*/true)) { printLog("Already asked"); @@ -944,11 +933,7 @@ void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, co printLog("Requested"); } else { LOCK(cs_data_requests); - CQuorumDataRequestKey key; - key.proRegTx = *pCurrentMemberHash; - key.flag = true; - key.quorumHash = pQuorum->qc->quorumHash; - key.llmqType = pQuorum->qc->llmqType; + const CQuorumDataRequestKey key(*pCurrentMemberHash, true, pQuorum->qc->quorumHash, pQuorum->qc->llmqType); auto it = mapQuorumDataRequests.find(key); if (it == mapQuorumDataRequests.end()) { printLog("Failed"); diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index 6e24d369d1..c254393322 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -39,14 +39,20 @@ static constexpr bool DEFAULT_WATCH_QUORUMS{false}; struct CQuorumDataRequestKey { uint256 proRegTx; - //TODO: Investigate purpose of this flag and rename accordingly - bool flag; + bool m_we_requested; uint256 quorumHash; Consensus::LLMQType llmqType; + CQuorumDataRequestKey(const uint256& proRegTxIn, const bool _m_we_requested, const uint256& quorumHashIn, const Consensus::LLMQType llmqTypeIn) : + proRegTx(proRegTxIn), + m_we_requested(_m_we_requested), + quorumHash(quorumHashIn), + llmqType(llmqTypeIn) + {} + bool operator ==(const CQuorumDataRequestKey& obj) const { - return (proRegTx == obj.proRegTx && flag == obj.flag && quorumHash == obj.quorumHash && llmqType == obj.llmqType); + return (proRegTx == obj.proRegTx && m_we_requested == obj.m_we_requested && quorumHash == obj.quorumHash && llmqType == obj.llmqType); } }; @@ -275,7 +281,7 @@ struct SaltedHasherImpl { CSipHasher c(k0, k1); c.Write((unsigned char*)&(v.proRegTx), sizeof(v.proRegTx)); - c.Write((unsigned char*)&(v.flag), sizeof(v.flag)); + c.Write((unsigned char*)&(v.m_we_requested), sizeof(v.m_we_requested)); c.Write((unsigned char*)&(v.quorumHash), sizeof(v.quorumHash)); c.Write((unsigned char*)&(v.llmqType), sizeof(v.llmqType)); return c.Finalize(); From 8afb8e975edbe527b0b1644150ef7da845f5f3da Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 5 Apr 2023 22:19:55 +0300 Subject: [PATCH 46/63] fix(qt): should use weighted mn count when calculating payments in Masternodes tab (#5287) ## Issue being fixed or feature implemented Masternodes tab was showing UNKNOWN next payment for some enabled MNs reported by @kxcd aka xkcd ## What was done? ask for the maximum data available, let GetProjectedMNPayees crop it ## How Has This Been Tested? run dash-qt, check the list on Masternodes tab ## 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 - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/evo/deterministicmns.h | 5 +++-- src/qt/masternodelist.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index 108cbbc75f..899435c941 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -19,6 +19,7 @@ #include +#include #include #include #include @@ -333,10 +334,10 @@ public: /** * Calculates the projected MN payees for the next *count* blocks. The result is not guaranteed to be correct * as PoSe banning might occur later - * @param count + * @param nCount the number of payees to return. "nCount = max()"" means "all", use it to avoid calling GetValidWeightedMNsCount twice. * @return */ - [[nodiscard]] std::vector GetProjectedMNPayees(int nCount) const; + [[nodiscard]] std::vector GetProjectedMNPayees(int nCount = std::numeric_limits::max()) const; /** * Calculate a quorum based on the modifier. The resulting list is deterministically sorted by score diff --git a/src/qt/masternodelist.cpp b/src/qt/masternodelist.cpp index 59c91e0096..e1ecb20664 100644 --- a/src/qt/masternodelist.cpp +++ b/src/qt/masternodelist.cpp @@ -202,7 +202,7 @@ void MasternodeList::updateDIP3List() nTimeUpdatedDIP3 = GetTime(); - auto projectedPayees = mnList.GetProjectedMNPayees(mnList.GetValidMNsCount()); + auto projectedPayees = mnList.GetProjectedMNPayees(); std::map nextPayments; for (size_t i = 0; i < projectedPayees.size(); i++) { const auto& dmn = projectedPayees[i]; From e8b5e4ac9314e2d5cd0380e3fc9a5fa8dcfa496e Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 4 Apr 2023 19:11:59 +0300 Subject: [PATCH 47/63] trivial(doc): fix typos in getrawtransaction and decoderawtransaction help texts (#5290) ## Issue being fixed or feature implemented fix typos in getrawtransaction and decoderawtransaction help texts ## What was done? tweak field name to match https://github.com/dashpay/dash/blob/develop/src/core_write.cpp#L192 ## How Has This Been Tested? ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/rpc/rawtransaction.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 9f90b07b0d..ff318b9344 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -143,7 +143,7 @@ static UniValue getrawtransaction(const JSONRPCRequest& request) {RPCResult::Type::STR_HEX, "txid", "The transaction id (same as provided)"}, {RPCResult::Type::NUM, "size", "The serialized transaction size"}, {RPCResult::Type::NUM, "version", "The version"}, - {RPCResult::Type::NUM, "version", "The type"}, + {RPCResult::Type::NUM, "type", "The type"}, {RPCResult::Type::NUM_TIME, "locktime", "The lock time"}, {RPCResult::Type::ARR, "vin", "", { @@ -494,7 +494,7 @@ static UniValue decoderawtransaction(const JSONRPCRequest& request) {RPCResult::Type::STR_HEX, "txid", "The transaction id"}, {RPCResult::Type::NUM, "size", "The transaction size"}, {RPCResult::Type::NUM, "version", "The version"}, - {RPCResult::Type::NUM, "version", "The type"}, + {RPCResult::Type::NUM, "type", "The type"}, {RPCResult::Type::NUM_TIME, "locktime", "The lock time"}, {RPCResult::Type::ARR, "vin", "", { From 9c8a6066b3e31b242d8c72e346241e8835cec339 Mon Sep 17 00:00:00 2001 From: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> Date: Tue, 4 Apr 2023 17:43:19 -0500 Subject: [PATCH 48/63] Merge pull request #5289 from UdjinM6/merge_master_18.2.2 chore: Merge master 18.2.2 back into develop --- doc/release-notes.md | 64 +++--- .../dash/release-notes-18.2.1.md | 187 ++++++++++++++++++ 2 files changed, 211 insertions(+), 40 deletions(-) create mode 100644 doc/release-notes/dash/release-notes-18.2.1.md diff --git a/doc/release-notes.md b/doc/release-notes.md index 53e4e78995..51c7891cb6 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -1,17 +1,15 @@ -Dash Core version v18.2.1 +Dash Core version v18.2.2 ========================= Release is now available from: -This is a new hotfix version release, bringing various bugfixes. +This is a new hotfix version release. -Please note that v18.2.0 was revoked due to a bug; this version fixes that bug. - -This release is optional for all nodes; however, v18.2.1 is required to be -able to use both mainnet and testnet. Currently, v18.2.0 is not working on mainnet, -and v18.1.1 is not working on testnet; v18.2.1 will work on both networks. +This release is optional for all nodes; however, v18.2.2 or higher is required +to be able to use testnet right until v19 hard fork activation. Earlier +versions will not be able to sync past block 847000 on testnet. Please report bugs using the issue tracker at GitHub: @@ -41,9 +39,9 @@ downgrade to an older version is only possible with a reindex Downgrade warning ----------------- -### Downgrade to a version < v18.2.1 +### Downgrade to a version < v18.2.2 -Downgrading to a version older than v18.2.1 is supported. +Downgrading to a version older than v18.2.2 is supported. ### Downgrade to a version < v18.0.1 @@ -51,35 +49,19 @@ Downgrading to a version older than v18.0.1 is not supported due to changes in the indexes database folder. If you need to use an older version, you must either reindex or re-sync the whole chain. -### Downgrade of masternodes to < 18.2.1 - -It is highly recommended not to downgrade masternodes below 18.2.1, as 18.2.1 (and 18.1.1) -fix important bugs which may result in your masternode being PoSe banned. - -### Downgrade of masternodes to < v18.0.1 - -Starting with the 0.16 release, masternodes verify the protocol version of other -masternodes. This results in PoSe punishment/banning for outdated masternodes, -so downgrading even prior to the activation of the introduced hard-fork changes -is not recommended. - -Versioning ----------- - -Dash Core imperfectly follows semantic versioning. Breaking changes should be -expected in a major release. The number and severity of breaking changes in minor -releases are minimized, however we do not guarantee there are no breaking changes. -Bitcoin backports often introduce breaking changes, and are a likely source of -breaking changes in minor releases. Patch releases should never contain breaking changes. - Notable changes =============== -See #5145 and #5142; these 2 PR fix important bugs in previous versions. Specifically, -#5145 fixes an issue where qfcommit messages can be replayed from the past, then are -validated and propagated to other nodes. This patch prevents old qfcommits -from being relayed. #5142 is a fix which enables this version to function both on testnet -and mainnet. +Testnet Breaking Changes +------------------------ + +A new testnet only LLMQ has been added. This LLMQ is of the type LLMQ_25_67; this LLMQ is only active on testnet. +This LLMQ will not remove the LLMQ_100_67 from testnet; however that quorum (likely) will not form and will perform no role. +See the [diff](https://github.com/dashpay/dash/pull/5225/files#diff-e70a38a3e8c2a63ca0494627301a5c7042141ad301193f78338d97cb1b300ff9R451-R469) for specific parameters of the LLMQ. + +This LLMQ will become active at the height of 847000. **This will be a breaking change and a hard fork for testnet** +This LLMQ is not activated with the v19 hardfork; as such testnet will experience two hardforks. One at height 847000, +and the other to be determined by the BIP9 hard fork process. Remote Procedure Call (RPC) Changes ----------------------------------- @@ -109,20 +91,21 @@ Backports from Bitcoin Core --------------------------- None -v18.2.1 Change log +Other changes +------------- +#5247 is backported to improve debugging experience. + +v18.2.2 Change log ================== -See detailed [set of changes](https://github.com/dashpay/dash/compare/v18.2.0...dashpay:v18.2.1). +See detailed [set of changes](https://github.com/dashpay/dash/compare/v18.2.1...dashpay:v18.2.2). Credits ======= Thanks to everyone who directly contributed to this release: -- Kittywhiskers Van Gogh -- Konstantin Akimov - Odysseas Gabrielides -- PastaPastaPasta - UdjinM6 As well as everyone that submitted issues, reviewed pull requests, helped debug the release candidates, and write DIPs that were implemented in this release. @@ -150,6 +133,7 @@ Dash Core tree 0.12.1.x was a fork of Bitcoin Core tree 0.12. These release are considered obsolete. Old release notes can be found here: +- [v18.2.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.2.2.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 diff --git a/doc/release-notes/dash/release-notes-18.2.1.md b/doc/release-notes/dash/release-notes-18.2.1.md new file mode 100644 index 0000000000..53e4e78995 --- /dev/null +++ b/doc/release-notes/dash/release-notes-18.2.1.md @@ -0,0 +1,187 @@ +Dash Core version v18.2.1 +========================= + +Release is now available from: + + + +This is a new hotfix version release, bringing various bugfixes. + +Please note that v18.2.0 was revoked due to a bug; this version fixes that bug. + +This release is optional for all nodes; however, v18.2.1 is required to be +able to use both mainnet and testnet. Currently, v18.2.0 is not working on mainnet, +and v18.1.1 is not working on testnet; v18.2.1 will work on both networks. + +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). If you upgrade after DIP0003 activation and you were +using version < 0.13 you will have to reindex (start with -reindex-chainstate +or -reindex) to make sure your wallet has all the new data synced. Upgrading +from version 0.13 should not require any additional actions. + +When upgrading from a version prior to 18.0.1, the +first startup of Dash Core will run a migration process which can take anywhere +from a few minutes to thirty minutes to finish. After the migration, a +downgrade to an older version is only possible with a reindex +(or reindex-chainstate). + +Downgrade warning +----------------- + +### Downgrade to a version < v18.2.1 + +Downgrading to a version older than v18.2.1 is supported. + +### Downgrade to a version < v18.0.1 + +Downgrading to a version older than v18.0.1 is not supported due to changes in +the indexes database folder. If you need to use an older version, you must +either reindex or re-sync the whole chain. + +### Downgrade of masternodes to < 18.2.1 + +It is highly recommended not to downgrade masternodes below 18.2.1, as 18.2.1 (and 18.1.1) +fix important bugs which may result in your masternode being PoSe banned. + +### Downgrade of masternodes to < v18.0.1 + +Starting with the 0.16 release, masternodes verify the protocol version of other +masternodes. This results in PoSe punishment/banning for outdated masternodes, +so downgrading even prior to the activation of the introduced hard-fork changes +is not recommended. + +Versioning +---------- + +Dash Core imperfectly follows semantic versioning. Breaking changes should be +expected in a major release. The number and severity of breaking changes in minor +releases are minimized, however we do not guarantee there are no breaking changes. +Bitcoin backports often introduce breaking changes, and are a likely source of +breaking changes in minor releases. Patch releases should never contain breaking changes. + +Notable changes +=============== +See #5145 and #5142; these 2 PR fix important bugs in previous versions. Specifically, +#5145 fixes an issue where qfcommit messages can be replayed from the past, then are +validated and propagated to other nodes. This patch prevents old qfcommits +from being relayed. #5142 is a fix which enables this version to function both on testnet +and mainnet. + + +Remote Procedure Call (RPC) Changes +----------------------------------- + +### The new RPCs are: +None + +### The removed RPCs are: +None + +### Changes in existing RPCs introduced through bitcoin backports: +None + +### Dash-specific changes in existing RPCs: +None + +Please check `help ` for more detailed information on specific RPCs. + +Command-line options +-------------------- +None + +Please check `Help -> Command-line options` in Qt wallet or `dashd --help` for +more information. + +Backports from Bitcoin Core +--------------------------- +None + +v18.2.1 Change log +================== + +See detailed [set of changes](https://github.com/dashpay/dash/compare/v18.2.0...dashpay:v18.2.1). + +Credits +======= + +Thanks to everyone who directly contributed to this release: + +- Kittywhiskers Van Gogh +- Konstantin Akimov +- Odysseas Gabrielides +- PastaPastaPasta +- UdjinM6 + +As well as everyone that submitted issues, reviewed pull requests, helped debug the release candidates, and write DIPs that were implemented in this release. + +Older releases +============== + +Dash was previously known as Darkcoin. + +Darkcoin tree 0.8.x was a fork of Litecoin tree 0.8, original name was XCoin +which was first released on Jan/18/2014. + +Darkcoin tree 0.9.x was the open source implementation of masternodes based on +the 0.8.x tree and was first released on Mar/13/2014. + +Darkcoin tree 0.10.x used to be the closed source implementation of Darksend +which was released open source on Sep/25/2014. + +Dash Core tree 0.11.x was a fork of Bitcoin Core tree 0.9, +Darkcoin was rebranded to Dash. + +Dash Core tree 0.12.0.x was a fork of Bitcoin Core tree 0.10. + +Dash Core tree 0.12.1.x was a fork of Bitcoin Core tree 0.12. + +These release are considered obsolete. Old release notes can be found here: + +- [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 From 7097e216d9cda718dc96b6ec7d7fd29f61698165 Mon Sep 17 00:00:00 2001 From: Oleg Girko Date: Thu, 6 Apr 2023 03:20:41 +0100 Subject: [PATCH 49/63] fix: Fix missing includes (#5295) The `` include is needed for `std::runtime_error` definition. The `` include is needed for `uint8_t` and `uint32_t` definition. ## Issue being fixed or feature implemented Compilation failure with GCC 13. GCC 13 is more strict about missing includes that were included indirectly by previous versions of GCC. ## What was done? Added missing includes. ## How Has This Been Tested? Successful compilation on Fedora 38 with GCC 13. All tests passed successfully. ## Breaking Changes None. ## 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 Signed-off-by: Oleg Girko Co-authored-by: Oleg Girko --- src/support/lockedpool.cpp | 1 + src/util/bip32.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp index bb27ba73a9..3681824e6a 100644 --- a/src/support/lockedpool.cpp +++ b/src/support/lockedpool.cpp @@ -23,6 +23,7 @@ #endif #include +#include #ifdef ARENA_DEBUG #include #include diff --git a/src/util/bip32.h b/src/util/bip32.h index fa1c0125f4..80f81384fa 100644 --- a/src/util/bip32.h +++ b/src/util/bip32.h @@ -6,6 +6,7 @@ #define BITCOIN_UTIL_BIP32_H #include +#include #include #include From fec09df98f1198cf674de99a85adb9acb562a90d Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 6 Apr 2023 17:19:32 +0300 Subject: [PATCH 50/63] fix(governance): use weighted mn count (#5299) ## Issue being fixed or feature implemented vote thresholds were counted incorrectly ## What was done? switch from `GetValidMNsCount()` to `GetValidWeightedMNsCount()` ## How Has This Been Tested? ... ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/governance/object.cpp | 8 ++++---- src/qt/governancelist.cpp | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/governance/object.cpp b/src/governance/object.cpp index 61b1043355..6d9f4f6150 100644 --- a/src/governance/object.cpp +++ b/src/governance/object.cpp @@ -711,13 +711,13 @@ void CGovernanceObject::UpdateSentinelVariables() { // CALCULATE MINIMUM SUPPORT LEVELS REQUIRED - int nMnCount = (int)deterministicMNManager->GetListAtChainTip().GetValidMNsCount(); - if (nMnCount == 0) return; + int nWeightedMnCount = (int)deterministicMNManager->GetListAtChainTip().GetValidWeightedMNsCount(); + if (nWeightedMnCount == 0) return; // CALCULATE THE MINIMUM VOTE COUNT REQUIRED FOR FULL SIGNAL - int nAbsVoteReq = std::max(Params().GetConsensus().nGovernanceMinQuorum, nMnCount / 10); - int nAbsDeleteReq = std::max(Params().GetConsensus().nGovernanceMinQuorum, (2 * nMnCount) / 3); + int nAbsVoteReq = std::max(Params().GetConsensus().nGovernanceMinQuorum, nWeightedMnCount / 10); + int nAbsDeleteReq = std::max(Params().GetConsensus().nGovernanceMinQuorum, (2 * nWeightedMnCount) / 3); // SET SENTINEL FLAGS TO FALSE diff --git a/src/qt/governancelist.cpp b/src/qt/governancelist.cpp index 0ced87e011..3c48d43ec6 100644 --- a/src/qt/governancelist.cpp +++ b/src/qt/governancelist.cpp @@ -344,11 +344,11 @@ void GovernanceList::setClientModel(ClientModel* model) void GovernanceList::updateProposalList() { if (this->clientModel) { - // A proposal is considered passing if (YES votes - NO votes) >= (Total Number of Masternodes / 10), + // A proposal is considered passing if (YES votes - NO votes) >= (Total Weight of Masternodes / 10), // count total valid (ENABLED) masternodes to determine passing threshold. // Need to query number of masternodes here with access to clientModel. - const int nMnCount = clientModel->getMasternodeList().GetValidMNsCount(); - const int nAbsVoteReq = std::max(Params().GetConsensus().nGovernanceMinQuorum, nMnCount / 10); + const int nWeightedMnCount = clientModel->getMasternodeList().GetValidWeightedMNsCount(); + const int nAbsVoteReq = std::max(Params().GetConsensus().nGovernanceMinQuorum, nWeightedMnCount / 10); proposalModel->setVotingParams(nAbsVoteReq); std::vector govObjList; From 088cfc30ab4c8a5d238524363857bed0c09f1195 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 6 Apr 2023 17:23:26 +0300 Subject: [PATCH 51/63] fix: add passed HPMN payments to the list in GetProjectedMNPayees (#5298) ## Issue being fixed or feature implemented Not having them in the list is 1. wrong 2. creates empty entries in results (nullptr-s) Should fix crashes like https://github.com/dashpay/dash/pull/5287#issuecomment-1498518599 ## What was done? Add missing entries ## How Has This Been Tested? Run dash-qt on testnet, wait when a HPMN is the payee. develop - crash, this PR - no crash. ## 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 - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/evo/deterministicmns.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index fe266149ad..f91214ccea 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -246,6 +246,14 @@ std::vector CDeterministicMNList::GetProjectedMNPayees(int result.emplace_back(dmn); } }); + + if (hpmn_to_be_skipped != nullptr) { + // if hpmn is in the middle of payments, add entries for already paid ones to the end of the list + for ([[maybe_unused]] auto _ : irange::range(hpmn_to_be_skipped->pdmnState->nConsecutivePayments)) { + result.emplace_back(hpmn_to_be_skipped); + } + } + std::sort(result.begin() + remaining_hpmn_payments, result.end(), [&](const CDeterministicMNCPtr& a, const CDeterministicMNCPtr& b) { return CompareByLastPaid(a.get(), b.get()); }); From b5b799ea8ba261c20930e4f3c6c1e065d28d93a9 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Thu, 6 Apr 2023 17:26:15 +0300 Subject: [PATCH 52/63] feat(qt): added hpmn count in qt information window (#5293) ## Issue being fixed or feature implemented ## What was done? Added a new label showing the number of total and enabled HPMN. The existing label was updated to show the number of total and enabled regular MNs instead. ## How Has This Been Tested? ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/qt/forms/debugwindow.ui | 60 ++++++++++++++++++++++++------------- src/qt/rpcconsole.cpp | 12 ++++++-- 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index d584d28fa8..9d99bff998 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -283,7 +283,7 @@ - Number of Masternodes + Number of regular Masternodes @@ -301,20 +301,40 @@ + + + Number of HPMNs + + + + + + + IBeamCursor + + + N/A + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + Block chain - + Current block height - + IBeamCursor @@ -330,14 +350,14 @@ - + Last block time - + IBeamCursor @@ -353,14 +373,14 @@ - + Last block hash - + IBeamCursor @@ -376,14 +396,14 @@ - + Latest ChainLocked block hash - + IBeamCursor @@ -399,14 +419,14 @@ - + Latest ChainLocked block height - + IBeamCursor @@ -422,21 +442,21 @@ - + Memory Pool - + Current number of transactions - + IBeamCursor @@ -452,14 +472,14 @@ - + Memory usage - + IBeamCursor @@ -475,7 +495,7 @@ - + 3 @@ -515,14 +535,14 @@ - + InstantSend locks - + IBeamCursor @@ -538,7 +558,7 @@ - + Qt::Vertical diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index cf862c93f9..4e973d3c00 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -958,10 +958,18 @@ void RPCConsole::updateMasternodeCount() return; } auto mnList = clientModel->getMasternodeList(); + size_t total_mn_count = mnList.GetAllMNsCount(); + size_t total_enabled_mn_count = mnList.GetValidMNsCount(); + size_t total_hpmn_count = mnList.GetAllHPMNsCount(); + size_t total_enabled_hpmn_count = mnList.GetValidHPMNsCount(); QString strMasternodeCount = tr("Total: %1 (Enabled: %2)") - .arg(QString::number(mnList.GetAllMNsCount())) - .arg(QString::number(mnList.GetValidMNsCount())); + .arg(QString::number(total_mn_count - total_hpmn_count)) + .arg(QString::number(total_enabled_mn_count - total_enabled_hpmn_count)); ui->masternodeCount->setText(strMasternodeCount); + QString strHPMNCount = tr("Total: %1 (Enabled: %2)") + .arg(QString::number(total_hpmn_count)) + .arg(QString::number(total_enabled_hpmn_count)); + ui->hpmnCount->setText(strHPMNCount); } void RPCConsole::setMempoolSize(long numberOfTxs, size_t dynUsage) From a326487a0845b2887a1885f74576cda8c09adb1f Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Thu, 6 Apr 2023 19:15:42 +0300 Subject: [PATCH 53/63] chore: v19 starttime and timeout bump (#5300) ## Issue being fixed or feature implemented ## What was done? Mainnet activation start time is set to: `Tuesday, April 25, 2023 0:00:00`, and timeout to: `Thursday, April 25, 2024 0:00:00` ## How Has This Been Tested? ## Breaking Changes ## 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 **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/chainparams.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index f2ed956850..50242562a1 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -238,8 +238,8 @@ public: // Deployment of Deployment of Basic BLS, AssetLocks, EHF consensus.vDeployments[Consensus::DEPLOYMENT_V19].bit = 8; - consensus.vDeployments[Consensus::DEPLOYMENT_V19].nStartTime = 1680220800; // Fri, Mar 31, 2023 0:00:00 - consensus.vDeployments[Consensus::DEPLOYMENT_V19].nTimeout = 1711843200; // Sun, Mar 31, 2024 00:00:00 + consensus.vDeployments[Consensus::DEPLOYMENT_V19].nStartTime = 1682380800; // Tuesday, April 25, 2023 0:00:00 + consensus.vDeployments[Consensus::DEPLOYMENT_V19].nTimeout = 1714003200; // Thursday, April 25, 2024 0:00:00 consensus.vDeployments[Consensus::DEPLOYMENT_V19].nWindowSize = 4032; consensus.vDeployments[Consensus::DEPLOYMENT_V19].nThresholdStart = 3226; // 80% of 4032 consensus.vDeployments[Consensus::DEPLOYMENT_V19].nThresholdMin = 2420; // 60% of 4032 From ebe5ef84a678b407aa1a50484a11c14c25f2d28a Mon Sep 17 00:00:00 2001 From: pasta Date: Wed, 5 Apr 2023 21:28:34 -0500 Subject: [PATCH 54/63] chore: bump to rc.10 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 91031f8156..f6183f9d84 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 19) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 9) +define(_CLIENT_VERSION_RC, 10) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2023) define(_COPYRIGHT_HOLDERS,[The %s developers]) From 93dc8076aa4f422063d878240e918960152ad6d8 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Mon, 10 Apr 2023 05:45:33 +0300 Subject: [PATCH 55/63] chore: Translations 2023-02 (#5208) --- src/qt/dashstrings.cpp | 12 +- src/qt/locale/dash_en.ts | 406 ++-- src/qt/locale/dash_en.xlf | 3892 +++++++++++++++++++------------------ src/qt/locale/dash_it.ts | 368 ++-- src/qt/locale/dash_pl.ts | 216 +- src/qt/locale/dash_ru.ts | 258 +-- 6 files changed, 2450 insertions(+), 2702 deletions(-) diff --git a/src/qt/dashstrings.cpp b/src/qt/dashstrings.cpp index 18bb4352a7..6f68fd88a1 100644 --- a/src/qt/dashstrings.cpp +++ b/src/qt/dashstrings.cpp @@ -73,8 +73,8 @@ QT_TRANSLATE_NOOP("dash-core", "" "Prune: last wallet synchronisation goes beyond pruned data. You need to -" "reindex (download the whole blockchain again in case of pruned node)"), QT_TRANSLATE_NOOP("dash-core", "" -"Rescans are not possible in pruned mode. You will need to use -reindex which " -"will download the whole blockchain again."), +"SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is " +"supported"), QT_TRANSLATE_NOOP("dash-core", "" "The block database contains a block which appears to be from the future. " "This may be due to your computer's date and time being set incorrectly. Only " @@ -165,12 +165,10 @@ 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"), QT_TRANSLATE_NOOP("dash-core", "Error loading block database"), -QT_TRANSLATE_NOOP("dash-core", "Error loading wallet %s. Duplicate -wallet filename specified."), 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: A fatal internal error occurred, see debug.log for details"), 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)"), @@ -190,8 +188,10 @@ 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", "Failed to verify database"), QT_TRANSLATE_NOOP("dash-core", "Found enough users, signing ( waiting %s )"), QT_TRANSLATE_NOOP("dash-core", "Found enough users, signing ..."), +QT_TRANSLATE_NOOP("dash-core", "Ignoring duplicate -wallet %s."), QT_TRANSLATE_NOOP("dash-core", "Importing..."), QT_TRANSLATE_NOOP("dash-core", "Incompatible mode."), QT_TRANSLATE_NOOP("dash-core", "Incompatible version."), @@ -247,6 +247,10 @@ 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", "SQLiteDatabase: Failed to execute statement to verify database: %s"), +QT_TRANSLATE_NOOP("dash-core", "SQLiteDatabase: Failed to prepare statement to verify database: %s"), +QT_TRANSLATE_NOOP("dash-core", "SQLiteDatabase: Failed to read database verification error: %s"), +QT_TRANSLATE_NOOP("dash-core", "SQLiteDatabase: Unexpected application id. Expected %u, got %u"), 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."), diff --git a/src/qt/locale/dash_en.ts b/src/qt/locale/dash_en.ts index a269f55073..c832bfc0a7 100644 --- a/src/qt/locale/dash_en.ts +++ b/src/qt/locale/dash_en.ts @@ -148,7 +148,7 @@ There was an error trying to save the address list to %1. Please try again. An error message. %1 is a name of the file (e.g., "addrbook.csv") that the bitcoin addresses were exported to. - There was an error trying to save the address list to %1. Please try again. + There was an error trying to save the address list to %1. Please try again. @@ -418,7 +418,7 @@ BitcoinGUI - + A fatal error occurred. Dash Core can no longer continue safely and will quit. A fatal error occurred. Dash Core can no longer continue safely and will quit. @@ -658,12 +658,7 @@ &Debug console - - Open debugging console - Open debugging console - - - + &Network Monitor &Network Monitor @@ -743,24 +738,24 @@ default wallet - + %1 client %1 client - + Wallet: %1 Wallet: %1 - + Wallet is <b>unencrypted</b> Wallet is <b>unencrypted</b> - + &File &File @@ -770,9 +765,14 @@ Show information about %1 - + + Open debugging and diagnostic console + Open debugging and diagnostic console + + + Open a dash: URI - + Open a dash: URI @@ -820,7 +820,7 @@ View Governance Proposals - + %n active connection(s) to Dash network %n active connection to Dash network @@ -838,7 +838,7 @@ Syncing Headers (%1%)... - + Synchronizing with network... Synchronizing with network... @@ -1005,7 +1005,7 @@ HD key generation is <b>enabled</b> - + Wallet is <b>encrypted</b> and currently <b>unlocked</b> Wallet is <b>encrypted</b> and currently <b>unlocked</b> @@ -1204,7 +1204,7 @@ (%1 locked) - + yes yes @@ -1283,7 +1283,7 @@ Creating Wallet <b>%1</b>... - + Create wallet failed Create wallet failed @@ -1452,7 +1452,7 @@ Filter proposal list - + Filter proposal list @@ -1465,7 +1465,7 @@ Filter by Title - + Proposal Info: %1 Proposal Info: %1 @@ -1589,12 +1589,12 @@ Form - + Status Status - + Filter List: Filter List: @@ -1623,6 +1623,11 @@ Service Service + + + Type + Type + PoSe Score @@ -1669,7 +1674,7 @@ Voting Address - + Copy ProTx Hash Copy ProTx Hash @@ -1684,7 +1689,7 @@ Updating... - + ENABLED ENABLED @@ -1721,13 +1726,13 @@ NONE - + Filter by any property (e.g. address or protx hash) Filter by any property (e.g. address or protx hash) - - + + Please wait... Please wait... @@ -1762,7 +1767,7 @@ - + Unknown... Unknown... @@ -1798,7 +1803,12 @@ Hide - + + Dash Core is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain. + Dash Core is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain. + + + Unknown. Syncing Headers (%1, %2%)... Unknown. Syncing Headers (%1, %2%)... @@ -1899,12 +1909,12 @@ Whether to keep the specified custom change address or not. - + Whether to keep the specified custom change address or not. Keep custom change &address - + Keep custom change &address @@ -2112,7 +2122,7 @@ Automatically open the Dash Core client port on the router. This only works when your router supports NAT-PMP and it is enabled. The external port could be random. - + Automatically open the Dash Core client port on the router. This only works when your router supports NAT-PMP and it is enabled. The external port could be random. @@ -2412,7 +2422,7 @@ https://www.transifex.com/projects/p/dash/ The denominations you submitted to the Masternode.<br>To mix, other users must submit the exact same denominations. - + out of sync @@ -2598,13 +2608,13 @@ https://www.transifex.com/projects/p/dash/ Cannot process payment request as BIP70 is no longer supported. - + Cannot process payment request as BIP70 is no longer supported. Due to discontinued support, you should request the merchant to provide you with a BIP21 compatible URI or use a wallet that does continue to support BIP70. - + Due to discontinued support, you should request the merchant to provide you with a BIP21 compatible URI or use a wallet that does continue to support BIP70. @@ -2625,7 +2635,7 @@ https://www.transifex.com/projects/p/dash/ PeerTableModel - + NodeId NodeId @@ -2658,7 +2668,7 @@ https://www.transifex.com/projects/p/dash/ Proposal - + Passing +%1 Passing +%1 @@ -2779,7 +2789,12 @@ https://www.transifex.com/projects/p/dash/ Error: %1 - + + Error initializing settings: %1 + Error initializing settings: %1 + + + Error: Failed to load application fonts. Error: Failed to load application fonts. @@ -2824,7 +2839,7 @@ https://www.transifex.com/projects/p/dash/ Amount - + Enter a Dash address (e.g. %1) Enter a Dash address (e.g. %1) @@ -2844,7 +2859,7 @@ https://www.transifex.com/projects/p/dash/ This can also be adjusted later in the "Appearance" tab of the preferences. - + %1 d %1 d @@ -2976,34 +2991,6 @@ https://www.transifex.com/projects/p/dash/ &Save Image... &Save Image... - - - Error creating QR Code. - Error creating QR Code. - - - - QRGeneralImageWidget - - - &Save Image... - &Save Image... - - - - &Copy Image - &Copy Image - - - - Save QR Code - Save QR Code - - - - PNG Image (*.png) - PNG Image (*.png) - QRImageWidget @@ -3102,7 +3089,7 @@ https://www.transifex.com/projects/p/dash/ - + N/A N/A @@ -3208,8 +3195,8 @@ https://www.transifex.com/projects/p/dash/ - - + + Select a peer to view detailed information. Select a peer to view detailed information. @@ -3244,7 +3231,7 @@ https://www.transifex.com/projects/p/dash/ Synced Blocks - + Rescan blockchain files 1 Rescan blockchain files 1 @@ -3254,12 +3241,12 @@ https://www.transifex.com/projects/p/dash/ Rescan blockchain files 2 - + The buttons below will restart the wallet with command-line options to repair the wallet, fix issues with corrupt blockchain files or missing/obsolete transactions. The buttons below will restart the wallet with command-line options to repair the wallet, fix issues with corrupt blockchain files or missing/obsolete transactions. - + -rescan=1: Rescan the block chain for missing wallet transactions starting from wallet creation time. -rescan=1: Rescan the block chain for missing wallet transactions starting from wallet creation time. @@ -3269,12 +3256,7 @@ https://www.transifex.com/projects/p/dash/ -rescan=2: Rescan the block chain for missing wallet transactions starting from genesis block. - - Wallet Path - Wallet Path - - - + User Agent User Agent @@ -3415,7 +3397,7 @@ https://www.transifex.com/projects/p/dash/ &Wallet Repair - + Upgrade wallet format Upgrade wallet format @@ -3425,12 +3407,12 @@ https://www.transifex.com/projects/p/dash/ -upgradewallet: Upgrade wallet to latest format on startup. (Note: this is NOT an update of the wallet itself!) - + Wallet repair options. Wallet repair options. - + Rebuild index Rebuild index @@ -3440,7 +3422,7 @@ https://www.transifex.com/projects/p/dash/ -reindex: Rebuild block chain index from current blk000??.dat files. - + &Disconnect &Disconnect @@ -3478,7 +3460,7 @@ https://www.transifex.com/projects/p/dash/ &Unban - + Welcome to the %1 RPC console. Welcome to the %1 RPC console. @@ -3549,15 +3531,20 @@ https://www.transifex.com/projects/p/dash/ never - + Inbound Inbound - + Outbound Outbound + + + Outbound block-relay + Outbound block-relay + Yes @@ -3603,8 +3590,7 @@ https://www.transifex.com/projects/p/dash/ &Message: - - + An optional label to associate with the new receiving address. An optional label to associate with the new receiving address. @@ -3614,7 +3600,12 @@ https://www.transifex.com/projects/p/dash/ An optional message to attach to the payment request, which will be displayed when the request is opened.<br>Note: The message will not be sent with the payment over the Dash network. - + + An optional label to associate with the new receiving address (used by you to identify an invoice). It is also attached to the payment request. + An optional label to associate with the new receiving address (used by you to identify an invoice). It is also attached to the payment request. + + + Use this form to request payments. All fields are <b>optional</b>. Use this form to request payments. All fields are <b>optional</b>. @@ -3776,7 +3767,7 @@ https://www.transifex.com/projects/p/dash/ RecentRequestsTableModel - + Date Date @@ -3815,7 +3806,7 @@ https://www.transifex.com/projects/p/dash/ SendCoinsDialog - + Send Coins Send Coins @@ -3897,12 +3888,12 @@ https://www.transifex.com/projects/p/dash/ When there is less transaction volume than space in the blocks, miners as well as relaying nodes may enforce a minimum fee. Paying only this minimum fee is just fine, but be aware that this can result in a never confirming transaction once there is more demand for dash transactions than the network can process. - + When there is less transaction volume than space in the blocks, miners as well as relaying nodes may enforce a minimum fee. Paying only this minimum fee is just fine, but be aware that this can result in a never confirming transaction once there is more demand for dash transactions than the network can process. A too low fee might result in a never confirming transaction (read the tooltip) - + A too low fee might result in a never confirming transaction (read the tooltip) @@ -3956,7 +3947,7 @@ https://www.transifex.com/projects/p/dash/ - + Confirm the send action Confirm the send action @@ -4032,34 +4023,28 @@ https://www.transifex.com/projects/p/dash/ %1 (%2 blocks) - - from wallet %1 - from wallet %1 - - - + using using - - + %1 to %2 %1 to %2 - + Are you sure you want to send? Are you sure you want to send? - + <b>(%1 of %2 entries displayed)</b> <b>(%1 of %2 entries displayed)</b> - + S&end mixed funds S&end mixed funds @@ -4069,7 +4054,37 @@ https://www.transifex.com/projects/p/dash/ Confirm the %1 send action - + + Cr&eate Unsigned + Cr&eate Unsigned + + + + Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet. + Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet. + + + + from wallet '%1' + from wallet '%1' + + + + %1 to '%2' + %1 to '%2' + + + + Do you want to draft this transaction? + Do you want to draft this transaction? + + + + This will produce a Partially Signed Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet. + This will produce a Partially Signed Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet. + + + %1 funds only %1 funds only @@ -4079,7 +4094,7 @@ https://www.transifex.com/projects/p/dash/ any available funds - + Transaction fee Transaction fee @@ -4126,13 +4141,38 @@ https://www.transifex.com/projects/p/dash/ or or + + + To review recipient list click "Show Details..." + To review recipient list click "Show Details..." + Confirm send coins Confirm send coins - + + Confirm transaction proposal + Confirm transaction proposal + + + + Copy PSBT to clipboard + Copy PSBT to clipboard + + + + Send + Send + + + + PSBT copied + PSBT copied + + + The recipient address is not valid. Please recheck. The recipient address is not valid. Please recheck. @@ -4172,7 +4212,7 @@ https://www.transifex.com/projects/p/dash/ Payment request expired. - + Estimated to begin confirmation within %n block(s). Estimated to begin confirmation within %n block. @@ -4315,15 +4355,6 @@ https://www.transifex.com/projects/p/dash/ Memo: - - SendConfirmationDialog - - - - Send - Send - - ShutdownWindow @@ -4479,26 +4510,26 @@ https://www.transifex.com/projects/p/dash/ - + The entered address is invalid. The entered address is invalid. - + + + - - Please check the address and try again. Please check the address and try again. - - + + The entered address does not refer to a key. The entered address does not refer to a key. - + Wallet unlock was cancelled. Wallet unlock was cancelled. @@ -4508,7 +4539,7 @@ https://www.transifex.com/projects/p/dash/ Private key for the entered address is not available. - + Message signing failed. Message signing failed. @@ -4518,18 +4549,18 @@ https://www.transifex.com/projects/p/dash/ Message signed. - + The signature could not be decoded. The signature could not be decoded. - - + + Please check the signature and try again. Please check the signature and try again. - + The signature did not match the message digest. The signature did not match the message digest. @@ -4539,7 +4570,7 @@ https://www.transifex.com/projects/p/dash/ Message verification failed. - + Message verified. Message verified. @@ -4952,7 +4983,7 @@ https://www.transifex.com/projects/p/dash/ watch-only - + (n/a) (n/a) @@ -5103,7 +5134,7 @@ https://www.transifex.com/projects/p/dash/ Resend transaction - + Resend transaction @@ -5242,7 +5273,7 @@ https://www.transifex.com/projects/p/dash/ WalletController - + Close wallet Close wallet @@ -5260,9 +5291,18 @@ https://www.transifex.com/projects/p/dash/ WalletFrame - - No wallet has been loaded. - No wallet has been loaded. + + No wallet has been loaded. +Go to File > Open Wallet to load a wallet. +- OR - + No wallet has been loaded. +Go to File > Open Wallet to load a wallet. +- OR - + + + + Create a new wallet + Create a new wallet @@ -5296,7 +5336,7 @@ https://www.transifex.com/projects/p/dash/ Selected amount: - + Backup Wallet Backup Wallet @@ -5414,7 +5454,7 @@ https://www.transifex.com/projects/p/dash/ Error loading block database - + Error opening block database Error opening block database @@ -5424,12 +5464,12 @@ https://www.transifex.com/projects/p/dash/ Error reading from database, shutting down. - + Failed to listen on any port. Use -listen=0 if you want this. Failed to listen on any port. Use -listen=0 if you want this. - + -maxtxfee is set very high! Fees this large could be paid on a single transaction. -maxtxfee is set very high! Fees this large could be paid on a single transaction. @@ -5454,7 +5494,12 @@ https://www.transifex.com/projects/p/dash/ Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions) - + + SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported + SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported + + + Transaction index can't be disabled with governance validation enabled. Either start with -disablegovernance command line switch or enable transaction index. Transaction index can't be disabled with governance validation enabled. Either start with -disablegovernance command line switch or enable transaction index. @@ -5469,7 +5514,7 @@ https://www.transifex.com/projects/p/dash/ Entry exceeds maximum size. - + Found enough users, signing ( waiting %s ) Found enough users, signing ( waiting %s ) @@ -5479,7 +5524,7 @@ https://www.transifex.com/projects/p/dash/ Found enough users, signing ... - + Importing... Importing... @@ -5579,7 +5624,7 @@ https://www.transifex.com/projects/p/dash/ Not in the Masternode list. - + Submitted to masternode, waiting in queue %s Submitted to masternode, waiting in queue %s @@ -5614,7 +5659,7 @@ https://www.transifex.com/projects/p/dash/ Will retry... - + Can't find random Masternode. Can't find random Masternode. @@ -5669,12 +5714,7 @@ https://www.transifex.com/projects/p/dash/ Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) - - Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. - Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. - - - + The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct @@ -5754,15 +5794,10 @@ https://www.transifex.com/projects/p/dash/ Error loading %s: Private keys can only be disabled during creation - + Error upgrading evo database Error upgrading evo database - - - Error: A fatal internal error occurred, see debug.log for details - Error: A fatal internal error occurred, see debug.log for details - Error: Disk space is low for %s @@ -5804,7 +5839,17 @@ https://www.transifex.com/projects/p/dash/ Failed to rescan the wallet during initialization - + + Failed to verify database + Failed to verify database + + + + Ignoring duplicate -wallet %s. + Ignoring duplicate -wallet %s. + + + Invalid P2P permission: '%s' Invalid P2P permission: '%s' @@ -5905,6 +5950,26 @@ https://www.transifex.com/projects/p/dash/ + SQLiteDatabase: Failed to execute statement to verify database: %s + SQLiteDatabase: Failed to execute statement to verify database: %s + + + + SQLiteDatabase: Failed to prepare statement to verify database: %s + SQLiteDatabase: Failed to prepare statement to verify database: %s + + + + SQLiteDatabase: Failed to read database verification error: %s + SQLiteDatabase: Failed to read database verification error: %s + + + + SQLiteDatabase: Unexpected application id. Expected %u, got %u + SQLiteDatabase: Unexpected application id. Expected %u, got %u + + + Section [%s] is not recognized. Section [%s] is not recognized. @@ -6046,7 +6111,7 @@ https://www.transifex.com/projects/p/dash/ see debug.log for details. - + The %s developers The %s developers @@ -6201,17 +6266,12 @@ https://www.transifex.com/projects/p/dash/ Error loading %s: You can't disable HD on an already existing HD wallet - - Error loading wallet %s. Duplicate -wallet filename specified. - Error loading wallet %s. Duplicate -wallet filename specified. - - - + Error upgrading chainstate database Error upgrading chainstate database - + Error: failed to add socket to kqueuefd (kevent returned error %s) Error: failed to add socket to kqueuefd (kevent returned error %s) @@ -6261,7 +6321,7 @@ https://www.transifex.com/projects/p/dash/ Failed to start a new mixing queue - + Incorrect -rescan mode, falling back to default value Incorrect -rescan mode, falling back to default value @@ -6316,7 +6376,7 @@ https://www.transifex.com/projects/p/dash/ Rescanning... - + Session not complete! Session not complete! @@ -6336,7 +6396,7 @@ https://www.transifex.com/projects/p/dash/ Specified blocks directory "%s" does not exist. - + Last queue was created too recently. Last queue was created too recently. @@ -6356,7 +6416,7 @@ https://www.transifex.com/projects/p/dash/ Last successful action was too recent. - + Starting network threads... Starting network threads... diff --git a/src/qt/locale/dash_en.xlf b/src/qt/locale/dash_en.xlf index c4049253d9..834e324751 100644 --- a/src/qt/locale/dash_en.xlf +++ b/src/qt/locale/dash_en.xlf @@ -433,354 +433,354 @@ A fatal error occurred. Dash Core can no longer continue safely and will quit. A fatal error occurred. Dash Core can no longer continue safely and will quit. - 395 + 396 Choose data directory on startup (default: %u) Choose data directory on startup (default: %u) - 409 + 410 Set the font family. Possible values: %1. (default: %2) Set the font family. Possible values: %1. (default: %2) - 411 + 412 Set a scale factor which gets applied to the base font size. Possible range %1 (smallest fonts) to %2 (largest fonts). (default: %3) Set a scale factor which gets applied to the base font size. Possible range %1 (smallest fonts) to %2 (largest fonts). (default: %3) - 412 + 413 Set the font weight for bold texts. Possible range %1 to %2 (default: %3) Set the font weight for bold texts. Possible range %1 to %2 (default: %3) - 413 + 414 Set the font weight for normal texts. Possible range %1 to %2 (default: %3) Set the font weight for normal texts. Possible range %1 to %2 (default: %3) - 414 + 415 Set language, for example "de_DE" (default: system locale) Set language, for example "de_DE" (default: system locale) - 415 + 416 Start minimized Start minimized - 416 + 417 Reset all settings changed in the GUI Reset all settings changed in the GUI - 417 + 418 Show splash screen on startup (default: %u) Show splash screen on startup (default: %u) - 418 + 419 Error: Specified data directory "%1" does not exist. Error: Specified data directory "%1" does not exist. - 526 + 527 Error: Cannot parse configuration file: %1. Error: Cannot parse configuration file: %1. - 532 + 533 Error: %1 Error: %1 - 547 + 548 - - Error: Failed to load application fonts. - Error: Failed to load application fonts. - 593 + + Error initializing settings: %1 + + 557 - Error: Specified font-family invalid. Valid values: %1. - Error: Specified font-family invalid. Valid values: %1. - 606 + Error: Failed to load application fonts. + Error: Failed to load application fonts. + 600 - Error: Specified font-weight-normal invalid. Valid range %1 to %2. - Error: Specified font-weight-normal invalid. Valid range %1 to %2. - 616 + Error: Specified font-family invalid. Valid values: %1. + Error: Specified font-family invalid. Valid values: %1. + 613 - Error: Specified font-weight-bold invalid. Valid range %1 to %2. - Error: Specified font-weight-bold invalid. Valid range %1 to %2. - 626 + Error: Specified font-weight-normal invalid. Valid range %1 to %2. + Error: Specified font-weight-normal invalid. Valid range %1 to %2. + 623 - Error: Specified font-scale invalid. Valid range %1 to %2. - Error: Specified font-scale invalid. Valid range %1 to %2. - 637 + Error: Specified font-weight-bold invalid. Valid range %1 to %2. + Error: Specified font-weight-bold invalid. Valid range %1 to %2. + 633 - Error: Invalid -custom-css-dir path. - Error: Invalid -custom-css-dir path. - 651 + Error: Specified font-scale invalid. Valid range %1 to %2. + Error: Specified font-scale invalid. Valid range %1 to %2. + 644 - Error: %1 CSS file(s) missing in -custom-css-dir path. - Error: %1 CSS file(s) missing in -custom-css-dir path. - 671 + Error: Invalid -custom-css-dir path. + Error: Invalid -custom-css-dir path. + 658 + Error: %1 CSS file(s) missing in -custom-css-dir path. + Error: %1 CSS file(s) missing in -custom-css-dir path. + 678 + + %1 didn't yet exit safely... %1 didn't yet exit safely... - 696 + 703 - + &Overview &Overview 650 - + Show general overview of wallet Show general overview of wallet 651 - + &Send &Send 345 - + Send coins to a Dash address Send coins to a Dash address 346 - + &Receive &Receive 354 - + Request payments (generates QR codes and dash: URIs) Request payments (generates QR codes and dash: URIs) 355 - + &Sending addresses &Sending addresses 425 - + &Receiving addresses &Receiving addresses 427 - + Open Wallet Open Wallet 433 - + Open a wallet Open a wallet 435 - + Close Wallet... Close Wallet... 438 - + Close wallet Close wallet 439 - + No wallets available No wallets available 518 - + &Window &Window 577 - + Minimize Minimize 579 - + Zoom Zoom 589 - + Main Window Main Window 607 - + &Transactions &Transactions 665 - + Browse transaction history Browse transaction history 666 - + &Masternodes &Masternodes 677 - + Browse masternodes Browse masternodes 678 - + E&xit E&xit 369 - + Quit application Quit application 370 - + About &Qt About &Qt 377 - + Show information about Qt Show information about Qt 378 - + &Options... &Options... 380 - + &About %1 &About %1 373 - + Send %1 funds to a Dash address Send %1 funds to a Dash address 351 - + Modify configuration options for %1 Modify configuration options for %1 381 - + &Show / Hide &Show / Hide 384 - + Show or hide the main Window Show or hide the main Window 385 - + &Encrypt Wallet... &Encrypt Wallet... 387 - + Encrypt the private keys that belong to your wallet Encrypt the private keys that belong to your wallet 388 - + &Backup Wallet... &Backup Wallet... 389 - + Backup wallet to another location Backup wallet to another location 390 - + &Change Passphrase... &Change Passphrase... 391 - + Change the passphrase used for wallet encryption Change the passphrase used for wallet encryption 392 - + &Unlock Wallet... &Unlock Wallet... 393 - + Unlock wallet Unlock wallet 394 - + &Lock Wallet &Lock Wallet 395 - + Sign &message... Sign &message... 396 - + Sign messages with your Dash addresses to prove you own them Sign messages with your Dash addresses to prove you own them 397 - + &Verify message... &Verify message... 398 - + Verify messages to ensure they were signed with specified Dash addresses Verify messages to ensure they were signed with specified Dash addresses 399 - + &Information &Information 401 - + Show diagnostic information Show diagnostic information 402 - + &Debug console &Debug console 403 - - Open debugging console - Open debugging console - 404 - &Network Monitor &Network Monitor @@ -864,19 +864,19 @@ %1 client %1 client - 968 + 977 Wallet: %1 Wallet: %1 - 1710 + 1721 Wallet is <b>unencrypted</b> Wallet is <b>unencrypted</b> - 1784 + 1796 &File @@ -889,378 +889,383 @@ 374 + Open debugging and diagnostic console + + 404 + + Open a dash: URI 431 - + Create Wallet... Create Wallet... 441 - + Create a new wallet Create a new wallet 443 - + %1 &information %1 &information 449 - + Show the %1 basic information Show the %1 basic information 451 - + &Settings &Settings 566 - + &Help &Help 627 - + Tabs toolbar Tabs toolbar 640 - + &Governance &Governance 686 - + View Governance Proposals View Governance Proposals 687 - 1225 - + 1234 + %n active connection(s) to Dash network %n active connection to Dash network - + %n active connection(s) to Dash network %n active connections to Dash network - + Network activity disabled Network activity disabled - 1227 - - - Syncing Headers (%1%)... - Syncing Headers (%1%)... - 1257 + 1236 - Synchronizing with network... - Synchronizing with network... - 1376 + Syncing Headers (%1%)... + Syncing Headers (%1%)... + 1266 - Indexing blocks on disk... - Indexing blocks on disk... - 1381 - - - Processing blocks on disk... - Processing blocks on disk... - 1383 - - - Reindexing blocks on disk... - Reindexing blocks on disk... + Synchronizing with network... + Synchronizing with network... 1387 + + Indexing blocks on disk... + Indexing blocks on disk... + 1392 + + + Processing blocks on disk... + Processing blocks on disk... + 1394 + + Reindexing blocks on disk... + Reindexing blocks on disk... + 1398 + + Connecting to peers... Connecting to peers... - 1393 + 1404 - 1402 - + 1413 + Processed %n block(s) of transaction history. Processed %n block of transaction history. - + Processed %n block(s) of transaction history. Processed %n blocks of transaction history. - + %1 behind %1 behind - 1421 - - - Catching up... - Catching up... - 1425 + 1432 - Last received block was generated %1 ago. - Last received block was generated %1 ago. - 1435 + Catching up... + Catching up... + 1436 - Transactions after this will not yet be visible. - Transactions after this will not yet be visible. - 1437 + Last received block was generated %1 ago. + Last received block was generated %1 ago. + 1446 - Up to date - Up to date - 1476 + Transactions after this will not yet be visible. + Transactions after this will not yet be visible. + 1448 - Synchronizing additional data: %p% - Synchronizing additional data: %p% - 1489 + Up to date + Up to date + 1487 - Error - Error - 1520 + Synchronizing additional data: %p% + Synchronizing additional data: %p% + 1500 - Error: %1 - Error: %1 - 1521 + Error + Error + 1531 - Warning - Warning - 1524 + Error: %1 + Error: %1 + 1532 - Warning: %1 - Warning: %1 - 1525 + Warning + Warning + 1535 - Information - Information - 1528 + Warning: %1 + Warning: %1 + 1536 - Received and sent multiple transactions - Received and sent multiple transactions - 1683 + Information + Information + 1539 - Sent multiple transactions - Sent multiple transactions - 1685 + Received and sent multiple transactions + Received and sent multiple transactions + 1694 - Received multiple transactions - Received multiple transactions - 1687 + Sent multiple transactions + Sent multiple transactions + 1696 + Received multiple transactions + Received multiple transactions + 1698 + + Sent Amount: %1 Sent Amount: %1 - 1697 + 1708 - + Received Amount: %1 Received Amount: %1 - 1700 + 1711 - + Date: %1 Date: %1 - 1707 + 1718 - + Amount: %1 Amount: %1 - 1708 + 1719 - + Type: %1 Type: %1 - 1712 + 1723 - + Label: %1 Label: %1 - 1714 + 1725 - + Address: %1 Address: %1 - 1716 - - - Sent transaction - Sent transaction - 1717 + 1727 - Incoming transaction - Incoming transaction - 1717 + Sent transaction + Sent transaction + 1728 - HD key generation is <b>enabled</b> - HD key generation is <b>enabled</b> - 1772 + Incoming transaction + Incoming transaction + 1728 - Wallet is <b>encrypted</b> and currently <b>unlocked</b> - Wallet is <b>encrypted</b> and currently <b>unlocked</b> - 1793 + HD key generation is <b>enabled</b> + HD key generation is <b>enabled</b> + 1783 - Wallet is <b>encrypted</b> and currently <b>unlocked</b> for mixing only - Wallet is <b>encrypted</b> and currently <b>unlocked</b> for mixing only - 1802 + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + 1805 - Wallet is <b>encrypted</b> and currently <b>locked</b> - Wallet is <b>encrypted</b> and currently <b>locked</b> - 1811 + Wallet is <b>encrypted</b> and currently <b>unlocked</b> for mixing only + Wallet is <b>encrypted</b> and currently <b>unlocked</b> for mixing only + 1814 - Proxy is <b>enabled</b>: %1 - Proxy is <b>enabled</b>: %1 - 1844 + Wallet is <b>encrypted</b> and currently <b>locked</b> + Wallet is <b>encrypted</b> and currently <b>locked</b> + 1823 + Proxy is <b>enabled</b>: %1 + Proxy is <b>enabled</b>: %1 + 1856 + + Original message: Original message: - 1945 + 1957 - + Unit to show amounts in. Click to select another unit. Unit to show amounts in. Click to select another unit. - 1986 + 1998 - + Quantity: Quantity: 42 - + Bytes: Bytes: 65 - + Amount: Amount: 104 - + Fee: Fee: 172 - + Coin Selection Coin Selection 14 - + Dust: Dust: 130 - + After Fee: After Fee: 211 - + Change: Change: 237 - + (un)select all (un)select all 293 - + toggle lock state toggle lock state 309 - + Tree mode Tree mode 341 - + List mode List mode 354 - + (1 locked) (1 locked) 364 - + Amount Amount 410 - + Received with label Received with label 415 - + Received with address Received with address 420 - + Mixing Rounds Mixing Rounds 425 - + Date Date 430 - + Confirmations Confirmations 435 - + Confirmed Confirmed 438 @@ -1269,202 +1274,202 @@ - + Copy address Copy address 66 - + Copy label Copy label 67 - + Copy amount Copy amount 68 94 - + Copy transaction ID Copy transaction ID 69 - + Lock unspent Lock unspent 70 - + Unlock unspent Unlock unspent 71 - + Copy quantity Copy quantity 93 - + Copy fee Copy fee 95 - + Copy after fee Copy after fee 96 - + Copy bytes Copy bytes 97 - + Copy dust Copy dust 98 - + Copy change Copy change 99 - + Please switch to "List mode" to use this function. Please switch to "List mode" to use this function. 236 - + (%1 locked) (%1 locked) 443 - + yes yes - 603 - - - no - no - 603 + 601 - This label turns red if any recipient receives an amount smaller than the current dust threshold. - This label turns red if any recipient receives an amount smaller than the current dust threshold. - 617 + no + no + 601 - Can vary +/- %1 duff(s) per input. - Can vary +/- %1 duff(s) per input. - 622 + This label turns red if any recipient receives an amount smaller than the current dust threshold. + This label turns red if any recipient receives an amount smaller than the current dust threshold. + 615 - Some coins were unselected because they were spent. - Some coins were unselected because they were spent. - 642 + Can vary +/- %1 duff(s) per input. + Can vary +/- %1 duff(s) per input. + 620 - Some coins were unselected because they do not have enough mixing rounds. - Some coins were unselected because they do not have enough mixing rounds. - 646 + Some coins were unselected because they were spent. + Some coins were unselected because they were spent. + 640 - Show all coins - Show all coins - 670 + Some coins were unselected because they do not have enough mixing rounds. + Some coins were unselected because they do not have enough mixing rounds. + 644 - Hide %1 coins - Hide %1 coins - 672 + Show all coins + Show all coins + 668 - Show all %1 coins - Show all %1 coins - 676 + Hide %1 coins + Hide %1 coins + 670 - Show spendable coins only - Show spendable coins only - 678 + Show all %1 coins + Show all %1 coins + 674 - (no label) - (no label) - 698 - 773 + Show spendable coins only + Show spendable coins only + 676 - change from %1 (%2) - change from %1 (%2) - 768 + (no label) + (no label) + 696 + 771 - (change) - (change) - 769 + change from %1 (%2) + change from %1 (%2) + 766 + (change) + (change) + 767 + + n/a n/a - 793 + 791 - + Creating Wallet <b>%1</b>... Creating Wallet <b>%1</b>... 216 - + Create wallet failed Create wallet failed - 242 + 241 - + Create wallet warning Create wallet warning - 244 + 243 - + Open wallet failed Open wallet failed - 283 - - - Open wallet warning - Open wallet warning - 285 + 282 - default wallet - default wallet - 295 + Open wallet warning + Open wallet warning + 284 + default wallet + default wallet + 294 + + Opening Wallet <b>%1</b>... Opening Wallet <b>%1</b>... - 297 + 296 - + Close wallet Close wallet 78 - + Are you sure you wish to close the wallet <i>%1</i>? Are you sure you wish to close the wallet <i>%1</i>? 79 - + Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled. Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled. 80 @@ -1473,42 +1478,42 @@ - + Create Wallet Create Wallet 14 - + Wallet Name Wallet Name 52 - + Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice. Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice. 65 - + Encrypt Wallet Encrypt Wallet 68 - + Disable private keys for this wallet. Wallets with private keys disabled will have no private keys and cannot have an HD seed or imported private keys. This is ideal for watch-only wallets. Disable private keys for this wallet. Wallets with private keys disabled will have no private keys and cannot have an HD seed or imported private keys. This is ideal for watch-only wallets. 87 - + Disable Private Keys Disable Private Keys 90 - + Make a blank wallet. Blank wallets do not initially have private keys or scripts. Private keys and addresses can be imported, or an HD seed can be set, at a later time. Make a blank wallet. Blank wallets do not initially have private keys or scripts. Private keys and addresses can be imported, or an HD seed can be set, at a later time. 103 - + Make Blank Wallet Make Blank Wallet 106 @@ -1517,7 +1522,7 @@ - + Create Create 19 @@ -1526,27 +1531,27 @@ - + Edit Address Edit Address 14 - + &Label &Label 25 - + The label associated with this address list entry The label associated with this address list entry 35 - + &Address &Address 42 - + The address associated with this address list entry. This can only be modified for sending addresses. The address associated with this address list entry. This can only be modified for sending addresses. 52 @@ -1555,42 +1560,42 @@ - + New sending address New sending address 31 - + Edit receiving address Edit receiving address 34 - + Edit sending address Edit sending address 38 - + The entered address "%1" is not a valid Dash address. The entered address "%1" is not a valid Dash address. 112 - + Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address. Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address. 145 - + The entered address "%1" is already in the address book with label "%2". The entered address "%1" is already in the address book with label "%2". 150 - + Could not unlock wallet. Could not unlock wallet. 122 - + New key generation failed. New key generation failed. 127 @@ -1599,69 +1604,69 @@ - + A new data directory will be created. A new data directory will be created. 74 - + name name 96 - + Directory already exists. Add %1 if you intend to create a new directory here. Directory already exists. Add %1 if you intend to create a new directory here. 98 - + Path already exists, and is not a directory. Path already exists, and is not a directory. 101 - + Cannot create data directory here. Cannot create data directory here. 108 - + At least %1 GB of data will be stored in this directory, and it will grow over time. At least %1 GB of data will be stored in this directory, and it will grow over time. 136 - + Approximately %1 GB of data will be stored in this directory. Approximately %1 GB of data will be stored in this directory. 141 - + %1 will download and store a copy of the Dash block chain. %1 will download and store a copy of the Dash block chain. 149 - + The wallet will also be stored in this directory. The wallet will also be stored in this directory. 151 - + Error: Specified data directory "%1" cannot be created. Error: Specified data directory "%1" cannot be created. 231 - + Error Error 259 - + %1 GB of free space available %1 GB of free space available 268 - + (of %1 GB needed) (of %1 GB needed) 271 @@ -1670,27 +1675,27 @@ - + Form Form 14 - + Filter List: Filter List: 57 - + Filter proposal list 64 - + Proposal Count: Proposal Count: 87 - + Filter by Title Filter by Title 67 @@ -1699,107 +1704,107 @@ - + Proposal Info: %1 Proposal Info: %1 - 403 + 408 - + Passing +%1 Passing +%1 - 81 + 85 - + Needs additional %1 votes Needs additional %1 votes - 83 + 87 - + Yes Yes - 137 - - - No - No - 137 + 141 - Hash - Hash - 177 + No + No + 141 - Title - Title - 179 - - - Start - Start + Hash + Hash 181 - - End - End + + Title + Title 183 - - Amount - Amount + + Start + Start 185 - - Active - Active + + End + End 187 + + Amount + Amount + 189 + + Active + Active + 191 + + Status Status - 189 + 193 - + version version 40 - + About %1 About %1 44 - + Command-line options Command-line options 64 - + %1 information %1 information 111 - + <h3>%1 Basics</h3> %1 gives you true financial privacy by obscuring the origins of your funds. All the Dash in your wallet is comprised of different "inputs" which you can think of as separate, discrete coins.<br> %1 uses an innovative process to mix your inputs with the inputs of two or more other people, without having your coins ever leave your wallet. You retain control of your money at all times.<hr> <b>The %1 process works like this:</b><ol type="1"> <li>%1 begins by breaking your transaction inputs down into standard denominations. These denominations are 0.001 DASH, 0.01 DASH, 0.1 DASH, 1 DASH and 10 DASH -- sort of like the paper money you use every day.</li> <li>Your wallet then sends requests to specially configured software nodes on the network, called "masternodes." These masternodes are informed then that you are interested in mixing a certain denomination. No identifiable information is sent to the masternodes, so they never know "who" you are.</li> <li>When two or more other people send similar messages, indicating that they wish to mix the same denomination, a mixing session begins. The masternode mixes up the inputs and instructs all three users' wallets to pay the now-transformed input back to themselves. Your wallet pays that denomination directly to itself, but in a different address (called a change address).</li> <li>In order to fully obscure your funds, your wallet must repeat this process a number of times with each denomination. Each time the process is completed, it's called a "round." Each round of %1 makes it exponentially more difficult to determine where your funds originated.</li> <li>This mixing process happens in the background without any intervention on your part. When you wish to make a transaction, your funds will already be mixed. No additional waiting is required.</li> </ol> <hr><b>IMPORTANT:</b> Your wallet only contains 1000 of these "change addresses." Every time a mixing event happens, up to 9 of your addresses are used up. This means those 1000 addresses last for about 100 mixing events. When 900 of them are used, your wallet must create more addresses. It can only do this, however, if you have automatic backups enabled.<br> Consequently, users who have backups disabled will also have %1 disabled. <hr>For more information, see the <a style="%2" href="%3">%1 documentation</a>. <h3>%1 Basics</h3> %1 gives you true financial privacy by obscuring the origins of your funds. All the Dash in your wallet is comprised of different "inputs" which you can think of as separate, discrete coins.<br> %1 uses an innovative process to mix your inputs with the inputs of two or more other people, without having your coins ever leave your wallet. You retain control of your money at all times.<hr> <b>The %1 process works like this:</b><ol type="1"> <li>%1 begins by breaking your transaction inputs down into standard denominations. These denominations are 0.001 DASH, 0.01 DASH, 0.1 DASH, 1 DASH and 10 DASH -- sort of like the paper money you use every day.</li> <li>Your wallet then sends requests to specially configured software nodes on the network, called "masternodes." These masternodes are informed then that you are interested in mixing a certain denomination. No identifiable information is sent to the masternodes, so they never know "who" you are.</li> <li>When two or more other people send similar messages, indicating that they wish to mix the same denomination, a mixing session begins. The masternode mixes up the inputs and instructs all three users' wallets to pay the now-transformed input back to themselves. Your wallet pays that denomination directly to itself, but in a different address (called a change address).</li> <li>In order to fully obscure your funds, your wallet must repeat this process a number of times with each denomination. Each time the process is completed, it's called a "round." Each round of %1 makes it exponentially more difficult to determine where your funds originated.</li> <li>This mixing process happens in the background without any intervention on your part. When you wish to make a transaction, your funds will already be mixed. No additional waiting is required.</li> </ol> <hr><b>IMPORTANT:</b> Your wallet only contains 1000 of these "change addresses." Every time a mixing event happens, up to 9 of your addresses are used up. This means those 1000 addresses last for about 100 mixing events. When 900 of them are used, your wallet must create more addresses. It can only do this, however, if you have automatic backups enabled.<br> Consequently, users who have backups disabled will also have %1 disabled. <hr>For more information, see the <a style="%2" href="%3">%1 documentation</a>. 115 - + %1 is shutting down... %1 is shutting down... 187 - + Do not shut down the computer until this window disappears. Do not shut down the computer until this window disappears. 188 @@ -1808,42 +1813,42 @@ - + Welcome Welcome 14 - + Welcome to %1. Welcome to %1. 23 - + As this is the first time the program is launched, you can choose where %1 will store its data. As this is the first time the program is launched, you can choose where %1 will store its data. 49 - + When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched. When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched. 206 - + This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off. This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off. 216 - + If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low. If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low. 226 - + Use the default data directory Use the default data directory 66 - + Use a custom data directory: Use a custom data directory: 73 @@ -1852,92 +1857,97 @@ - + Form Form 14 - + Status Status - 137 + 142 - + Filter List: Filter List: 57 - + Filter masternode list Filter masternode list 64 - + Node Count: Node Count: 97 - + Show only masternodes this wallet has keys for. Show only masternodes this wallet has keys for. 74 - + My masternodes only My masternodes only 77 - + Service Service 132 - - PoSe Score - PoSe Score - 142 - - - Registered - Registered - 147 + + Type + Type + 137 - Last Paid - Last Paid - 152 + PoSe Score + PoSe Score + 147 - Next Payment - Next Payment - 157 + Registered + Registered + 152 - Payout Address - Payout Address - 162 + Last Paid + Last Paid + 157 - Operator Reward - Operator Reward - 167 + Next Payment + Next Payment + 162 - Collateral Address - Collateral Address - 172 + Payout Address + Payout Address + 167 - Owner Address - Owner Address - 177 + Operator Reward + Operator Reward + 172 - Voting Address - Voting Address - 182 + Collateral Address + Collateral Address + 177 + Owner Address + Owner Address + 182 + + + Voting Address + Voting Address + 187 + + Filter by any property (e.g. address or protx hash) Filter by any property (e.g. address or protx hash) 67 @@ -1946,127 +1956,127 @@ - + Copy ProTx Hash Copy ProTx Hash - 89 - - - Copy Collateral Outpoint - Copy Collateral Outpoint - 90 - - - Updating... - Updating... - 192 + 95 - ENABLED - ENABLED - 229 + Copy Collateral Outpoint + Copy Collateral Outpoint + 96 - POSE_BANNED - POSE_BANNED - 229 + Updating... + Updating... + 198 - UNKNOWN - UNKNOWN - 229 - 243 - 266 + ENABLED + ENABLED + 236 - to %1 - to %1 - 256 + POSE_BANNED + POSE_BANNED + 236 - to UNKNOWN - to UNKNOWN - 258 + UNKNOWN + UNKNOWN + 236 + 250 + 273 - but not claimed - but not claimed - 261 + to %1 + to %1 + 263 - NONE - NONE - 249 + to UNKNOWN + to UNKNOWN + 265 - Please wait... - Please wait... - 151 - 321 + but not claimed + but not claimed + 268 + NONE + NONE + 256 + + + Please wait... + Please wait... + 157 + 330 + + Additional information for DIP3 Masternode %1 Additional information for DIP3 Masternode %1 - 369 + 378 - + Form Form 14 - + Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the Dash network, as detailed below. Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the Dash network, as detailed below. 114 - + Attempting to spend Dash that are affected by not-yet-displayed transactions will not be accepted by the network. Attempting to spend Dash that are affected by not-yet-displayed transactions will not be accepted by the network. 127 - + Number of blocks left Number of blocks left 187 - + Unknown... Unknown... 194 214 - ../modaloverlay.cpp154 + ../modaloverlay.cpp158 - + Last block time Last block time 201 - + Progress Progress 221 - + Progress increase per hour Progress increase per hour 239 - + calculating... calculating... 246 260 - + Estimated time left until synced Estimated time left until synced 253 - + Hide Hide 290 @@ -2075,28 +2085,33 @@ - + + Dash Core is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain. + + 48 + + Unknown. Syncing Headers (%1, %2%)... Unknown. Syncing Headers (%1, %2%)... - 160 + 164 - + unknown unknown - 125 + 129 - + Open URI Open URI 14 - + URI: URI: 22 @@ -2105,396 +2120,396 @@ - + Options Options 20 - + &Main &Main 37 - + Size of &database cache Size of &database cache 217 - + Number of script &verification threads Number of script &verification threads 260 - + (0 = auto, <0 = leave that many cores free) (0 = auto, <0 = leave that many cores free) 273 - + W&allet W&allet 47 - + &Appearance &Appearance 87 - + Prune &block storage to Prune &block storage to 170 - + GB GB 180 - + Reverting this setting requires re-downloading the entire blockchain. Reverting this setting requires re-downloading the entire blockchain. 205 - + MiB MiB 233 - + Whether to keep the specified custom change address or not. 324 - + Keep custom change &address 327 - + Show additional tab listing all your masternodes in first sub-tab<br/>and all masternodes on the network in second sub-tab. Show additional tab listing all your masternodes in first sub-tab<br/>and all masternodes on the network in second sub-tab. 334 - + Show Masternodes Tab Show Masternodes Tab 337 - + Show additional tab listing governance proposals. Show additional tab listing governance proposals. 344 - + Show Governance Tab Show Governance Tab 347 - + If you disable the spending of unconfirmed change, the change from a transaction<br/>cannot be used until that transaction has at least one confirmation.<br/>This also affects how your balance is computed. If you disable the spending of unconfirmed change, the change from a transaction<br/>cannot be used until that transaction has at least one confirmation.<br/>This also affects how your balance is computed. 354 - + Show mixing interface on Overview screen and reveal an additional screen which allows to spend fully mixed coins only.<br/>A new tab with more settings will also appear in this dialog, please make sure to check them before mixing your coins. Show mixing interface on Overview screen and reveal an additional screen which allows to spend fully mixed coins only.<br/>A new tab with more settings will also appear in this dialog, please make sure to check them before mixing your coins. 364 - + Show additional information and buttons on overview screen. Show additional information and buttons on overview screen. 393 - + Enable advanced interface Enable advanced interface 396 - + Show system popups for mixing transactions<br/>just like for all other transaction types. Show system popups for mixing transactions<br/>just like for all other transaction types. 403 - + Show popups for mixing transactions Show popups for mixing transactions 406 - + Show warning dialog when the wallet has very low number of keys left. Show warning dialog when the wallet has very low number of keys left. 413 - + Warn if the wallet is running out of keys Warn if the wallet is running out of keys 416 - + Whether to use experimental mode with multiple mixing sessions per block.<br/>Note: You must use this feature carefully.<br/>Make sure you always have recent wallet (auto)backup in a safe place! Whether to use experimental mode with multiple mixing sessions per block.<br/>Note: You must use this feature carefully.<br/>Make sure you always have recent wallet (auto)backup in a safe place! 423 - + Enable &multi-session Enable &multi-session 426 - + Mixing rounds Mixing rounds 438 - + This amount acts as a threshold to turn off mixing once it's reached. This amount acts as a threshold to turn off mixing once it's reached. 462 - + Target balance Target balance 477 - + Automatically open the Dash Core client port on the router. This only works when your router supports UPnP and it is enabled. Automatically open the Dash Core client port on the router. This only works when your router supports UPnP and it is enabled. 519 - + Map port using NA&T-PMP Map port using NA&T-PMP 532 - + Accept connections from outside. Accept connections from outside. 539 - + Allow incomin&g connections Allow incomin&g connections 542 - + Connect to the Dash network through a SOCKS5 proxy. Connect to the Dash network through a SOCKS5 proxy. 549 - + &Connect through SOCKS5 proxy (default proxy): &Connect through SOCKS5 proxy (default proxy): 552 - + Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type. Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type. 655 668 681 - + Use separate SOCKS&5 proxy to reach peers via Tor hidden services: Use separate SOCKS&5 proxy to reach peers via Tor hidden services: 709 - + Options set in this dialog are overridden by the command line or in the configuration file: Options set in this dialog are overridden by the command line or in the configuration file: 981 - + Hide the icon from the system tray. Hide the icon from the system tray. 135 - + &Hide tray icon &Hide tray icon 138 - + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu. Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu. 155 - + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items.<br/>%s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items.<br/>%s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. 914 927 - + &Third party transaction URLs &Third party transaction URLs 917 - + Whether to show coin control features or not. Whether to show coin control features or not. 314 - + Automatically start %1 after logging in to the system. Automatically start %1 after logging in to the system. 112 - + &Start %1 on system login &Start %1 on system login 115 - + Enable coin &control features Enable coin &control features 317 - + &Spend unconfirmed change &Spend unconfirmed change 357 - + This setting determines the amount of individual masternodes that an input will be mixed through.<br/>More rounds of mixing gives a higher degree of privacy, but also costs more in fees. This setting determines the amount of individual masternodes that an input will be mixed through.<br/>More rounds of mixing gives a higher degree of privacy, but also costs more in fees. 435 - + &Network &Network 67 - + Enabling pruning significantly reduces the disk space required to store transactions. All blocks are still fully validated. Reverting this setting requires re-downloading the entire blockchain. Enabling pruning significantly reduces the disk space required to store transactions. All blocks are still fully validated. Reverting this setting requires re-downloading the entire blockchain. 167 - + Map port using &UPnP Map port using &UPnP 522 - + Automatically open the Dash Core client port on the router. This only works when your router supports NAT-PMP and it is enabled. The external port could be random. 529 - + Proxy &IP: Proxy &IP: 561 718 - + IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) 586 743 - + &Port: &Port: 593 750 - + Port of the proxy (e.g. 9050) Port of the proxy (e.g. 9050) 618 775 - + Used for reaching peers via: Used for reaching peers via: 642 - + IPv4 IPv4 658 - + IPv6 IPv6 671 - + Tor Tor 684 - + Connect to the Dash network through a separate SOCKS5 proxy for Tor hidden services. Connect to the Dash network through a separate SOCKS5 proxy for Tor hidden services. 706 - + Show only a tray icon after minimizing the window. Show only a tray icon after minimizing the window. 145 - + &Minimize to the tray instead of the taskbar &Minimize to the tray instead of the taskbar 148 - + M&inimize on close M&inimize on close 158 - + &Display &Display 77 - + User Interface &language: User Interface &language: 816 - + The user interface language can be set here. This setting will take effect after restarting %1. The user interface language can be set here. This setting will take effect after restarting %1. 829 - + Language missing or translation incomplete? Help contributing translations here: https://www.transifex.com/projects/p/dash/ Language missing or translation incomplete? Help contributing translations here: https://www.transifex.com/projects/p/dash/ 850 - + &Unit to show amounts in: &Unit to show amounts in: 876 - + Choose the default subdivision unit to show in the interface and when sending coins. Choose the default subdivision unit to show in the interface and when sending coins. 889 - + Decimal digits Decimal digits 900 - + Reset all client options to default. Reset all client options to default. 1027 - + &Reset Options &Reset Options 1030 - + &OK &OK 1085 - + &Cancel &Cancel 1098 @@ -2503,38 +2518,38 @@ https://www.transifex.com/projects/p/dash/ - + Enable %1 features Enable %1 features 69 - + default default 146 - + Confirm options reset Confirm options reset 379 - + Client restart required to activate changes. Client restart required to activate changes. 380 436 - + Client will be shut down. Do you want to proceed? Client will be shut down. Do you want to proceed? 380 - + This change would require a client restart. This change would require a client restart. 440 - + The supplied proxy address is invalid. The supplied proxy address is invalid. 468 @@ -2543,139 +2558,139 @@ https://www.transifex.com/projects/p/dash/ - + Form Form 20 - + The displayed information may be out of date. Your wallet automatically synchronizes with the Dash network after a connection is established, but this process has not completed yet. The displayed information may be out of date. Your wallet automatically synchronizes with the Dash network after a connection is established, but this process has not completed yet. 80 378 615 - + Available: Available: 290 - + Your current spendable balance Your current spendable balance 300 - + Pending: Pending: 335 - + Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance 135 - + Immature: Immature: 235 - + Mined balance that has not yet matured Mined balance that has not yet matured 206 - + Balances Balances 73 - + Unconfirmed transactions to watch-only addresses Unconfirmed transactions to watch-only addresses 116 - + Mined balance in watch-only addresses that has not yet matured Mined balance in watch-only addresses that has not yet matured 154 - + Total: Total: 196 - + Your current total balance Your current total balance 245 - + Current total balance in watch-only addresses Current total balance in watch-only addresses 264 - + Watch-only: Watch-only: 280 - + Your current balance in watch-only addresses Your current balance in watch-only addresses 319 - + Spendable: Spendable: 342 - + Status: Status: 417 - + Enabled/Disabled Enabled/Disabled 424 - + Completion: Completion: 431 - + Amount and Rounds: Amount and Rounds: 465 - + 0 DASH / 0 Rounds 0 DASH / 0 Rounds 472 - + Submitted Denom: Submitted Denom: 479 - + n/a n/a 489 - + Recent transactions Recent transactions 608 - + Start/Stop Mixing Start/Stop Mixing 527 - + The denominations you submitted to the Masternode.<br>To mix, other users must submit the exact same denominations. The denominations you submitted to the Masternode.<br>To mix, other users must submit the exact same denominations. 486 @@ -2684,184 +2699,184 @@ https://www.transifex.com/projects/p/dash/ - + out of sync out of sync - 151 - 152 153 + 154 + 155 - + Automatic backups are disabled, no mixing available! Automatic backups are disabled, no mixing available! - 454 + 456 - + No inputs detected No inputs detected - 340 - 346 + 342 + 348 - + %1 Balance %1 Balance - 157 + 159 - 344 - 364 - 375 - + 346 + 366 + 377 + %n Rounds %n Round - + %n Rounds %n Rounds - + Found enough compatible inputs to mix %1 Found enough compatible inputs to mix %1 - 361 - - - Not enough compatible inputs to mix <span style='%1'>%2</span>,<br>will mix <span style='%1'>%3</span> instead - Not enough compatible inputs to mix <span style='%1'>%2</span>,<br>will mix <span style='%1'>%3</span> instead - 367 - - - Overall progress - Overall progress - 426 - - - Denominated - Denominated - 427 + 363 - Partially mixed - Partially mixed - 428 + Not enough compatible inputs to mix <span style='%1'>%2</span>,<br>will mix <span style='%1'>%3</span> instead + Not enough compatible inputs to mix <span style='%1'>%2</span>,<br>will mix <span style='%1'>%3</span> instead + 369 - Mixed - Mixed + Overall progress + Overall progress + 428 + + + Denominated + Denominated 429 - + + Partially mixed + Partially mixed 430 - + + + Mixed + Mixed + 431 + + + 432 + Denominated inputs have %5 of %n rounds on average Denominated inputs have %5 of %n round on average - + Denominated inputs have %5 of %n rounds on average Denominated inputs have %5 of %n rounds on average - + keys left: %1 keys left: %1 - 512 - - - Start %1 - Start %1 - 526 - 659 - - - If you don't want to see internal %1 fees/transactions select "Most Common" as Type on the "Transactions" tab. - If you don't want to see internal %1 fees/transactions select "Most Common" as Type on the "Transactions" tab. - 622 - - - %1 requires at least %2 to use. - %1 requires at least %2 to use. - 633 + 514 - Wallet is locked and user declined to unlock. Disabling %1. - Wallet is locked and user declined to unlock. Disabling %1. - 647 + Start %1 + Start %1 + 528 + 661 - Stop %1 - Stop %1 - 663 + If you don't want to see internal %1 fees/transactions select "Most Common" as Type on the "Transactions" tab. + If you don't want to see internal %1 fees/transactions select "Most Common" as Type on the "Transactions" tab. + 624 - Disabled - Disabled - 528 - 582 - 699 - 702 + %1 requires at least %2 to use. + %1 requires at least %2 to use. + 635 - Very low number of keys left since last automatic backup! - Very low number of keys left since last automatic backup! - 547 + Wallet is locked and user declined to unlock. Disabling %1. + Wallet is locked and user declined to unlock. Disabling %1. + 649 - We are about to create a new automatic backup for you, however <span style='%1'> you should always make sure you have backups saved in some safe place</span>! - We are about to create a new automatic backup for you, however <span style='%1'> you should always make sure you have backups saved in some safe place</span>! - 548 + Stop %1 + Stop %1 + 665 - Note: You can turn this message off in options. - Note: You can turn this message off in options. - 551 + Disabled + Disabled + 530 + 584 + 701 + 704 - WARNING! Something went wrong on automatic backup - WARNING! Something went wrong on automatic backup - 567 + Very low number of keys left since last automatic backup! + Very low number of keys left since last automatic backup! + 549 - ERROR! Failed to create automatic backup - ERROR! Failed to create automatic backup - 575 - 591 + We are about to create a new automatic backup for you, however <span style='%1'> you should always make sure you have backups saved in some safe place</span>! + We are about to create a new automatic backup for you, however <span style='%1'> you should always make sure you have backups saved in some safe place</span>! + 550 - Mixing is disabled, please close your wallet and fix the issue! - Mixing is disabled, please close your wallet and fix the issue! - 576 - 593 + Note: You can turn this message off in options. + Note: You can turn this message off in options. + 553 - Enabled - Enabled - 582 + WARNING! Something went wrong on automatic backup + WARNING! Something went wrong on automatic backup + 569 - see debug.log for details. - see debug.log for details. - 592 + ERROR! Failed to create automatic backup + ERROR! Failed to create automatic backup + 577 + 593 + Mixing is disabled, please close your wallet and fix the issue! + Mixing is disabled, please close your wallet and fix the issue! + 578 + 595 + + + Enabled + Enabled + 584 + + + see debug.log for details. + see debug.log for details. + 594 + + WARNING! Failed to replenish keypool, please unlock your wallet to do so. WARNING! Failed to replenish keypool, please unlock your wallet to do so. - 599 + 601 - + Payment request error Payment request error 175 - + Cannot start dash: click-to-pay handler Cannot start dash: click-to-pay handler 176 - + URI handling URI handling 226 @@ -2869,34 +2884,34 @@ https://www.transifex.com/projects/p/dash/ 244 252 - + 'dash://' is not a valid URI. Use 'dash:' instead. 'dash://' is not a valid URI. Use 'dash:' instead. 226 - + Cannot process payment request as BIP70 is no longer supported. 240 263 - + Due to discontinued support, you should request the merchant to provide you with a BIP21 compatible URI or use a wallet that does continue to support BIP70. 241 264 - + Invalid payment address %1 Invalid payment address %1 244 - + URI cannot be parsed! This can be caused by an invalid Dash address or malformed URI parameters. URI cannot be parsed! This can be caused by an invalid Dash address or malformed URI parameters. 253 - + Payment request file handling Payment request file handling 262 @@ -2905,41 +2920,41 @@ https://www.transifex.com/projects/p/dash/ - + NodeId NodeId - 110 - - - Node/Service - Node/Service - 110 - - - User Agent - User Agent - 110 - - - Ping - Ping - 110 + 108 - Sent - Sent - 110 + Node/Service + Node/Service + 108 + User Agent + User Agent + 108 + + + Ping + Ping + 108 + + + Sent + Sent + 108 + + Received Received - 110 + 108 - + Amount Amount 233 @@ -2948,239 +2963,208 @@ https://www.transifex.com/projects/p/dash/ - + Enter a Dash address (e.g. %1) Enter a Dash address (e.g. %1) - 272 - - - Appearance Setup - Appearance Setup - 284 - - - Please choose your preferred settings for the appearance of %1 - Please choose your preferred settings for the appearance of %1 - 287 - - - This can also be adjusted later in the "Appearance" tab of the preferences. - This can also be adjusted later in the "Appearance" tab of the preferences. - 290 + 280 - %1 d - %1 d - 1742 + Appearance Setup + Appearance Setup + 292 - %1 h - %1 h - 1744 + Please choose your preferred settings for the appearance of %1 + Please choose your preferred settings for the appearance of %1 + 295 - %1 m - %1 m - 1746 + This can also be adjusted later in the "Appearance" tab of the preferences. + This can also be adjusted later in the "Appearance" tab of the preferences. + 298 - %1 s - %1 s - 1748 - 1774 + %1 d + %1 d + 1749 - None - None - 1764 + %1 h + %1 h + 1751 - N/A - N/A - 1769 + %1 m + %1 m + 1753 + %1 s + %1 s + 1755 + 1781 + + + None + None + 1771 + + + N/A + N/A + 1776 + + %1 ms %1 ms - 1769 + 1776 - 1787 - + 1794 + %n second(s) %n second - + %n second(s) %n seconds - 1791 - + 1798 + %n minute(s) %n minute - + %n minute(s) %n minutes - 1795 - + 1802 + %n hour(s) %n hour - + %n hour(s) %n hours - 1799 - + 1806 + %n day(s) %n day - + %n day(s) %n days - 1803 - 1809 - + 1810 + 1816 + %n week(s) %n week - + %n week(s) %n weeks - 1809 - + 1816 + %n year(s) %n year - + %n year(s) %n years - + %1 and %2 %1 and %2 - 1809 - - - %1 B - %1 B - 1817 - - - %1 KB - %1 KB - 1819 - - - %1 MB - %1 MB - 1821 + 1816 + %1 B + %1 B + 1824 + + + %1 KB + %1 KB + 1826 + + + %1 MB + %1 MB + 1828 + + %1 GB %1 GB - 1823 + 1830 - + QR-Code Title QR-Code Title 17 - + QR Code QR Code 39 - + &Save Image... &Save Image... 85 - - - - Error creating QR Code. - Error creating QR Code. - 142 - - - - - &Save Image... - &Save Image... - 36 - - - &Copy Image - &Copy Image - 39 - - - Save QR Code - Save QR Code - 71 - - - PNG Image (*.png) - PNG Image (*.png) - 71 - - - - + &Save Image... &Save Image... 29 - + &Copy Image &Copy Image 32 - + Resulting URI too long, try to reduce the text for label / message. Resulting URI too long, try to reduce the text for label / message. 45 - + Error encoding URI into QR Code. Error encoding URI into QR Code. 52 - + QR code support not available. QR code support not available. 101 - + Save QR Code Save QR Code 133 - + PNG Image (*.png) PNG Image (*.png) 133 @@ -3189,27 +3173,27 @@ https://www.transifex.com/projects/p/dash/ - + Tools window Tools window 14 - + &Information &Information 28 - + General General 96 - + Name Name 240 - + N/A N/A 113 @@ -3248,587 +3232,591 @@ https://www.transifex.com/projects/p/dash/ 1313 1336 1359 - ../rpcconsole.cpp1226 + ../rpcconsole.cpp1247 - + Number of connections Number of connections 263 - + &Open &Open 509 - + Startup time Startup time 210 - + Network Network 233 - + Last block time Last block time 336 - + Debug log file Debug log file 499 - + Client version Client version 103 - + Block chain Block chain 306 - + Number of Masternodes Number of Masternodes 286 - + Memory Pool Memory Pool 428 - + Current number of transactions Current number of transactions 435 - + Memory usage Memory usage 458 - + &Console &Console 38 - + Clear console Clear console 618 - + &Network Traffic &Network Traffic 48 - + Received Received 1254 - + Sent Sent 1231 - + &Peers &Peers 58 - + Wallet: Wallet: 572 - + Banned peers Banned peers 806 - + Select a peer to view detailed information. Select a peer to view detailed information. 869 - ../rpcconsole.cpp515 - ../rpcconsole.cpp1393 + ../rpcconsole.cpp513 + ../rpcconsole.cpp1414 - + Whitelisted Whitelisted 952 - + Direction Direction 975 - + Version Version 998 - + Starting Block Starting Block 1070 - + Synced Headers Synced Headers 1093 - + Synced Blocks Synced Blocks 1116 - + Rescan blockchain files 1 Rescan blockchain files 1 - 1433 + 1430 - + Rescan blockchain files 2 Rescan blockchain files 2 - 1456 + 1453 - + The buttons below will restart the wallet with command-line options to repair the wallet, fix issues with corrupt blockchain files or missing/obsolete transactions. The buttons below will restart the wallet with command-line options to repair the wallet, fix issues with corrupt blockchain files or missing/obsolete transactions. 1410 - + -rescan=1: Rescan the block chain for missing wallet transactions starting from wallet creation time. -rescan=1: Rescan the block chain for missing wallet transactions starting from wallet creation time. - 1440 + 1437 - + -rescan=2: Rescan the block chain for missing wallet transactions starting from genesis block. -rescan=2: Rescan the block chain for missing wallet transactions starting from genesis block. - 1463 + 1460 - - Wallet Path - Wallet Path - 1420 - - + User Agent User Agent 126 1021 - + Datadir Datadir 152 - + To specify a non-default location of the data directory use the '%1' option. To specify a non-default location of the data directory use the '%1' option. 162 - + Blocksdir Blocksdir 181 - + To specify a non-default location of the blocks directory use the '%1' option. To specify a non-default location of the blocks directory use the '%1' option. 191 - + Current block height Current block height 313 - + Last block hash Last block hash 359 - + Latest ChainLocked block hash Latest ChainLocked block hash 382 - + Latest ChainLocked block height Latest ChainLocked block height 405 - + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. 506 - + InstantSend locks InstantSend locks 521 - + (none) (none) 583 - + Decrease font size Decrease font size 604 - + Increase font size Increase font size 611 - + &Reset &Reset 723 - + Node Type Node Type 906 - + PoSe Score PoSe Score 929 - + Services Services 1047 - + Ban Score Ban Score 1139 - + Connection Time Connection Time 1162 - + Last Send Last Send 1185 - + Last Receive Last Receive 1208 - + Ping Time Ping Time 1277 - + The duration of a currently outstanding ping. The duration of a currently outstanding ping. 1300 - + Ping Wait Ping Wait 1303 - + Min Ping Min Ping 1326 - + Time Offset Time Offset 1349 - + &Wallet Repair &Wallet Repair 68 - + Upgrade wallet format Upgrade wallet format - 1479 + 1476 - + -upgradewallet: Upgrade wallet to latest format on startup. (Note: this is NOT an update of the wallet itself!) -upgradewallet: Upgrade wallet to latest format on startup. (Note: this is NOT an update of the wallet itself!) - 1486 + 1483 - + Wallet repair options. Wallet repair options. 1400 - + Rebuild index Rebuild index - 1496 + 1493 - + -reindex: Rebuild block chain index from current blk000??.dat files. -reindex: Rebuild block chain index from current blk000??.dat files. - 1503 + 1500 - + &Disconnect &Disconnect + 621 + + + Ban for + Ban for + 622 + 623 + 624 + 625 + + + 1 &hour + 1 &hour + 622 + + + 1 &day + 1 &day 623 - Ban for - Ban for - 624 - 625 - 626 - 627 - - - 1 &hour - 1 &hour - 624 - - - 1 &day - 1 &day - 625 - - 1 &week 1 &week - 626 + 624 - + 1 &year 1 &year - 627 + 625 - + &Unban &Unban - 664 + 662 - + Welcome to the %1 RPC console. Welcome to the %1 RPC console. - 877 + 894 - + Use up and down arrows to navigate history, and %1 to clear screen. Use up and down arrows to navigate history, and %1 to clear screen. - 878 + 895 - + Type %1 for an overview of available commands. Type %1 for an overview of available commands. - 879 + 896 - + For more information on using this console type %1. For more information on using this console type %1. - 880 + 897 - + WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command. WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command. - 882 + 899 - + In: In: - 913 + 930 - + Out: Out: - 914 + 931 - + Network activity disabled Network activity disabled - 917 + 934 - + Total: %1 (Enabled: %2) Total: %1 (Enabled: %2) - 957 + 974 - + Executing command without any wallet Executing command without any wallet - 1025 + 1042 - + Executing command using "%1" wallet Executing command using "%1" wallet - 1023 + 1040 - + (node id: %1) (node id: %1) - 1204 + 1221 - + via %1 via %1 - 1206 + 1223 - + never never - 1209 - 1210 + 1226 + 1227 - + Inbound Inbound - 1220 + 1238 - + Outbound Outbound - 1220 + 1240 - + + Outbound block-relay + + 1241 + + Yes Yes - 1222 + 1243 - + No No - 1222 + 1243 - + Regular Regular - 1225 + 1246 - + Masternode Masternode - 1229 + 1250 - + Verified Masternode Verified Masternode - 1231 + 1252 - + Unknown Unknown - 1246 - 1252 + 1267 + 1273 - + An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Dash network. An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Dash network. 34 - + &Message: &Message: 37 - + An optional label to associate with the new receiving address. An optional label to associate with the new receiving address. - 50 77 - + An optional message to attach to the payment request, which will be displayed when the request is opened.<br>Note: The message will not be sent with the payment over the Dash network. An optional message to attach to the payment request, which will be displayed when the request is opened.<br>Note: The message will not be sent with the payment over the Dash network. 60 - + + An optional label to associate with the new receiving address (used by you to identify an invoice). It is also attached to the payment request. + + 50 + + Use this form to request payments. All fields are <b>optional</b>. Use this form to request payments. All fields are <b>optional</b>. 70 - + &Label: &Label: 80 - + An optional amount to request. Leave this empty or zero to not request a specific amount. An optional amount to request. Leave this empty or zero to not request a specific amount. 93 179 - + &Amount: &Amount: 96 - + &Create new receiving address &Create new receiving address 117 - + Clear all fields of the form. Clear all fields of the form. 136 - + Clear Clear 139 - + Requested payments history Requested payments history 234 - + Show the selected request (does the same as double clicking an entry) Show the selected request (does the same as double clicking an entry) 259 - + Show Show 262 - + Remove the selected entries from the list Remove the selected entries from the list 275 - + Remove Remove 278 - + Enter a label to associate with the new receiving address Enter a label to associate with the new receiving address 53 - + Enter a message to attach to the payment request Enter a message to attach to the payment request 63 @@ -3837,27 +3825,27 @@ https://www.transifex.com/projects/p/dash/ - + Copy URI Copy URI 35 - + Copy address Copy address 36 - + Copy label Copy label 37 - + Copy message Copy message 38 - + Copy amount Copy amount 39 @@ -3866,22 +3854,22 @@ https://www.transifex.com/projects/p/dash/ - + QR Code QR Code 29 - + Copy &URI Copy &URI 75 - + Copy &Address Copy &Address 85 - + &Save Image... &Save Image... 95 @@ -3890,42 +3878,42 @@ https://www.transifex.com/projects/p/dash/ - + Request payment to %1 Request payment to %1 66 - + Payment information Payment information 72 - + URI URI 73 - + Address Address 76 - + Amount Amount 78 - + Label Label 80 - + Message Message 82 - + Wallet Wallet 84 @@ -3934,219 +3922,219 @@ https://www.transifex.com/projects/p/dash/ - + Date Date - 27 + 26 - + Label Label - 27 + 26 - + Message Message - 27 + 26 - + (no label) (no label) - 68 + 67 - + (no message) (no message) - 77 + 76 - + (no amount requested) (no amount requested) - 85 + 84 - + Requested Requested - 127 + 126 - + Send Coins Send Coins 14 - ../sendcoinsdialog.cpp672 + ../sendcoinsdialog.cpp706 - + Coin Control Features Coin Control Features 81 - + Inputs... Inputs... 101 - + automatically selected automatically selected 111 - + Insufficient funds! Insufficient funds! 121 - + Quantity: Quantity: 204 - + Bytes: Bytes: 233 - + Amount: Amount: 275 - + Fee: Fee: 343 - + Dust: Dust: 301 - + After Fee: After Fee: 388 - + Change: Change: 414 - + If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. 458 - + Custom change address Custom change address 461 - + Transaction Fee: Transaction Fee: 658 - + Choose... Choose... 672 - + When there is less transaction volume than space in the blocks, miners as well as relaying nodes may enforce a minimum fee. Paying only this minimum fee is just fine, but be aware that this can result in a never confirming transaction once there is more demand for dash transactions than the network can process. 822 - + A too low fee might result in a never confirming transaction (read the tooltip) 825 - + Confirmation time target: Confirmation time target: 968 - + If the custom fee is set to 1000 duffs and the transaction is only 250 bytes, then "per kilobyte" only pays 250 duffs in fee,<br />while "at least" pays 1000 duffs. For transactions bigger than a kilobyte both pay by kilobyte. If the custom fee is set to 1000 duffs and the transaction is only 250 bytes, then "per kilobyte" only pays 250 duffs in fee,<br />while "at least" pays 1000 duffs. For transactions bigger than a kilobyte both pay by kilobyte. 789 - + per kilobyte per kilobyte 792 - + Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain. Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain. 694 - + Note: Not enough data for fee estimation, using the fallback fee instead. Note: Not enough data for fee estimation, using the fallback fee instead. 697 - + Hide transaction fee settings Hide transaction fee settings 735 - + Hide Hide 738 - + Recommended: Recommended: 857 - + Custom: Custom: 890 - + (Smart fee not initialized yet. This usually takes a few blocks...) (Smart fee not initialized yet. This usually takes a few blocks...) 942 - + Confirm the send action Confirm the send action 1055 - ../sendcoinsdialog.cpp149 + ../sendcoinsdialog.cpp150 - + S&end S&end 1058 - ../sendcoinsdialog.cpp148 + ../sendcoinsdialog.cpp149 - + Clear all fields of the form. Clear all fields of the form. 1077 - + Clear &All Clear &All 1080 - + Send to multiple recipients at once Send to multiple recipients at once 1090 - + Add &Recipient Add &Recipient 1093 - + Balance: Balance: 1121 @@ -4155,339 +4143,380 @@ https://www.transifex.com/projects/p/dash/ - + Copy quantity Copy quantity - 103 - - - Copy amount - Copy amount 104 - - Copy fee - Copy fee + + Copy amount + Copy amount 105 - - Copy after fee - Copy after fee + + Copy fee + Copy fee 106 - - Copy bytes - Copy bytes + + Copy after fee + Copy after fee 107 - - Copy dust - Copy dust + + Copy bytes + Copy bytes 108 - - Copy change - Copy change + + Copy dust + Copy dust 109 - + + Copy change + Copy change + 110 + + %1 (%2 blocks) %1 (%2 blocks) - 203 + 204 - - from wallet %1 - from wallet %1 - 325 - - + using using - 370 - 372 + 377 + 379 - + %1 to %2 %1 to %2 - 338 - 343 + 347 - + Are you sure you want to send? Are you sure you want to send? - 362 + 363 - + <b>(%1 of %2 entries displayed)</b> <b>(%1 of %2 entries displayed)</b> - 378 - - - S&end mixed funds - S&end mixed funds - 145 - - - Confirm the %1 send action - Confirm the %1 send action - 146 - - - %1 funds only - %1 funds only - 370 - - - any available funds - any available funds - 372 - - - Transaction fee - Transaction fee 388 - - (%1 transactions have higher fees usually due to no change output being allowed) - (%1 transactions have higher fees usually due to no change output being allowed) - 394 + + S&end mixed funds + S&end mixed funds + 146 + + + Confirm the %1 send action + Confirm the %1 send action + 147 + + + Cr&eate Unsigned + + 220 + + + Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet. + + 221 + + + from wallet '%1' + + 331 + + + %1 to '%2' + + 342 + + + Do you want to draft this transaction? + + 361 + + + This will produce a Partially Signed Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet. + + 367 - Transaction size: %1 - Transaction size: %1 - 401 + %1 funds only + %1 funds only + 377 - Fee rate: %1 - Fee rate: %1 + any available funds + any available funds + 379 + + + Transaction fee + Transaction fee + 398 + + + (%1 transactions have higher fees usually due to no change output being allowed) + (%1 transactions have higher fees usually due to no change output being allowed) 404 + + Transaction size: %1 + Transaction size: %1 + 411 + + + Fee rate: %1 + Fee rate: %1 + 414 + - 410 - + 420 + This transaction will consume %n input(s) This transaction will consume %n input - + This transaction will consume %n input(s) This transaction will consume %n inputs - + Warning: Using %1 with %2 or more inputs can harm your privacy and is not recommended Warning: Using %1 with %2 or more inputs can harm your privacy and is not recommended - 416 - - - Click to learn more - Click to learn more - 418 - - - Total Amount - Total Amount - 435 - - - or - or - 438 - - - Confirm send coins - Confirm send coins - 441 + 426 - The recipient address is not valid. Please recheck. - The recipient address is not valid. Please recheck. - 641 + Click to learn more + Click to learn more + 428 - The amount to pay must be larger than 0. - The amount to pay must be larger than 0. - 644 + Total Amount + Total Amount + 445 - The amount exceeds your balance. - The amount exceeds your balance. - 647 + or + or + 448 - - The total exceeds your balance when the %1 transaction fee is included. - The total exceeds your balance when the %1 transaction fee is included. - 650 + + To review recipient list click "Show Details..." + + 453 + Confirm send coins + Confirm send coins + 456 + + + Confirm transaction proposal + + 456 + + + Copy PSBT to clipboard + + 457 + + + Send + Send + 457 + + + PSBT copied + + 480 + + + The recipient address is not valid. Please recheck. + The recipient address is not valid. Please recheck. + 675 + + + The amount to pay must be larger than 0. + The amount to pay must be larger than 0. + 678 + + + The amount exceeds your balance. + The amount exceeds your balance. + 681 + + + The total exceeds your balance when the %1 transaction fee is included. + The total exceeds your balance when the %1 transaction fee is included. + 684 + + Duplicate address found: addresses should only be used once each. Duplicate address found: addresses should only be used once each. - 653 + 687 - + Transaction creation failed! Transaction creation failed! - 656 + 690 - + A fee higher than %1 is considered an absurdly high fee. A fee higher than %1 is considered an absurdly high fee. - 660 + 694 - + Payment request expired. Payment request expired. - 663 + 697 - 771 - + 810 + Estimated to begin confirmation within %n block(s). Estimated to begin confirmation within %n block. - + Estimated to begin confirmation within %n block(s). Estimated to begin confirmation within %n blocks. - + Warning: Invalid Dash address Warning: Invalid Dash address - 872 + 911 - + Warning: Unknown change address Warning: Unknown change address - 877 + 916 - + Confirm custom change address Confirm custom change address - 880 + 919 - + The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure? The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure? - 880 + 919 - + (no label) (no label) - 901 - - - - - Send - Send - 991 - 996 + 940 - + Pay &To: Pay &To: 39 - + The Dash address to send the payment to The Dash address to send the payment to 57 - + Choose previously used address Choose previously used address 64 - + Alt+A Alt+A 76 - + Paste address from clipboard Paste address from clipboard 83 - + Alt+P Alt+P 95 - + Remove this entry Remove this entry 102 660 1189 - + &Label: &Label: 120 - + Enter a label for this address to add it to the list of used addresses Enter a label for this address to add it to the list of used addresses 133 136 - + A&mount: A&mount: 143 689 1218 - + The amount to send in the selected unit The amount to send in the selected unit 158 - + The fee will be deducted from the amount being sent. The recipient will receive a lower amount of Dash than you enter in the amount field. If multiple recipients are selected, the fee is split equally. The fee will be deducted from the amount being sent. The recipient will receive a lower amount of Dash than you enter in the amount field. If multiple recipients are selected, the fee is split equally. 165 - + S&ubtract fee from amount S&ubtract fee from amount 168 - + Use available balance Use available balance 175 - + Message: Message: 184 - + A message that was attached to the dash: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Dash network. A message that was attached to the dash: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Dash network. 194 - + This is an unauthenticated payment request. This is an unauthenticated payment request. 627 - + This is an authenticated payment request. This is an authenticated payment request. 1152 - + Pay To: Pay To: 642 1167 - + Memo: Memo: 672 @@ -4497,140 +4526,140 @@ https://www.transifex.com/projects/p/dash/ - + Signatures - Sign / Verify a Message Signatures - Sign / Verify a Message 14 - + &Sign Message &Sign Message 31 - + You can sign messages/agreements with your addresses to prove you can receive Dash sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. You can sign messages/agreements with your addresses to prove you can receive Dash sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. 66 - + The Dash address to sign the message with The Dash address to sign the message with 84 - + Choose previously used address Choose previously used address 91 264 - + Alt+A Alt+A 97 270 - + Paste address from clipboard Paste address from clipboard 104 - + Alt+P Alt+P 110 - + Enter the message you want to sign here Enter the message you want to sign here 119 - + Signature Signature 129 - + Copy the current signature to the system clipboard Copy the current signature to the system clipboard 154 - + Sign the message to prove you own this Dash address Sign the message to prove you own this Dash address 168 - + Sign &Message Sign &Message 171 - + Reset all sign message fields Reset all sign message fields 181 - + Clear &All Clear &All 184 317 - + &Verify Message &Verify Message 41 - + Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction! Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction! 236 - + The Dash address the message was signed with The Dash address the message was signed with 257 - + The signed message to verify The signed message to verify 279 - + The signature given when the message was signed The signature given when the message was signed 289 - + Verify the message to ensure it was signed with the specified Dash address Verify the message to ensure it was signed with the specified Dash address 301 - + Verify &Message Verify &Message 304 - + Reset all verify message fields Reset all verify message fields 314 - + Enter a message to be signed Enter a message to be signed 122 - + Click "Sign Message" to generate signature Click "Sign Message" to generate signature 144 - + Enter a message to be verified Enter a message to be verified 282 - + Enter a signature for the message to be verified Enter a signature for the message to be verified 292 @@ -4639,77 +4668,77 @@ https://www.transifex.com/projects/p/dash/ - + The entered address is invalid. The entered address is invalid. 145 - 223 + 237 - + Please check the address and try again. Please check the address and try again. 145 152 - 223 - 229 + 238 + 245 - + The entered address does not refer to a key. The entered address does not refer to a key. 152 - 229 + 244 - + Wallet unlock was cancelled. Wallet unlock was cancelled. 160 - + Private key for the entered address is not available. Private key for the entered address is not available. 168 - + Message signing failed. Message signing failed. - 180 + 177 - + Message signed. Message signed. - 185 + 182 - + The signature could not be decoded. The signature could not be decoded. - 240 + 251 - + Please check the signature and try again. Please check the signature and try again. - 240 - 253 - - - The signature did not match the message digest. - The signature did not match the message digest. - 253 - - - Message verification failed. - Message verification failed. + 252 259 - + + The signature did not match the message digest. + The signature did not match the message digest. + 258 + + + Message verification failed. + Message verification failed. + 264 + + Message verified. Message verified. - 264 + 232 - + [testnet] [testnet] 25 @@ -4718,22 +4747,22 @@ https://www.transifex.com/projects/p/dash/ - + KB/s KB/s 101 - + Total Total 166 - + Received Received 167 - + Sent Sent 168 @@ -4744,121 +4773,121 @@ https://www.transifex.com/projects/p/dash/ 33 - + Open for %n more block(s) Open for %n more block - + Open for %n more block(s) Open for %n more blocks - + Open until %1 Open until %1 35 - + conflicted conflicted 40 - + 0/unconfirmed, %1 0/unconfirmed, %1 46 - + in memory pool in memory pool 46 - + not in memory pool not in memory pool 46 - + abandoned abandoned 46 - + %1/unconfirmed %1/unconfirmed 48 - + %1 confirmations %1 confirmations 50 - + locked via ChainLocks locked via ChainLocks 52 - + verified via InstantSend verified via InstantSend 58 - + Status Status 83 - + Date Date 86 - + Source Source 93 - + Generated Generated 93 - + From From 98 112 184 - + unknown unknown 112 - + To To 113 133 203 - + own address own address 115 - + watch-only watch-only 115 184 - + label label 117 - + Credit Credit 153 @@ -4869,105 +4898,105 @@ https://www.transifex.com/projects/p/dash/ 155 - + matures in %n more block(s) matures in %n more block - + matures in %n more block(s) matures in %n more blocks - + not accepted not accepted 157 - + Debit Debit 217 243 289 - + Total debit Total debit 227 - + Total credit Total credit 228 - + Transaction fee Transaction fee 233 - + Net amount Net amount 255 - + Message Message 261 272 - + Comment Comment 263 - + Transaction ID Transaction ID 265 - + Output index Output index 266 - + Transaction total size Transaction total size 267 - + Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. 278 - + Debug information Debug information 286 - + Transaction Transaction 294 - + Inputs Inputs 297 - + Amount Amount 318 - + true true 319 320 - + false false 319 @@ -4977,7 +5006,7 @@ https://www.transifex.com/projects/p/dash/ - + This pane shows a detailed description of the transaction This pane shows a detailed description of the transaction 20 @@ -4986,7 +5015,7 @@ https://www.transifex.com/projects/p/dash/ - + Details for %1 Details for %1 21 @@ -4995,418 +5024,418 @@ https://www.transifex.com/projects/p/dash/ - + Date Date 231 - + Type Type 231 - + Address / Label Address / Label 231 309 - + Open for %n more block(s) Open for %n more block - + Open for %n more block(s) Open for %n more blocks - + Open until %1 Open until %1 312 - + Unconfirmed Unconfirmed 315 - + Abandoned Abandoned 318 - + Confirming (%1 of %2 recommended confirmations) Confirming (%1 of %2 recommended confirmations) 321 - + Confirmed (%1 confirmations) Confirmed (%1 confirmations) 324 - + Conflicted Conflicted 327 - + Immature (%1 confirmations, will be available after %2) Immature (%1 confirmations, will be available after %2) 330 - + Generated but not accepted Generated but not accepted 333 - + verified via InstantSend verified via InstantSend 338 - + locked via ChainLocks locked via ChainLocks 341 - + Received with Received with 378 - + Received from Received from 380 - + Received via %1 Received via %1 382 - + Sent to Sent to 385 - + Payment to yourself Payment to yourself 387 - + Mined Mined 389 - + %1 Mixing %1 Mixing 392 - + %1 Collateral Payment %1 Collateral Payment 394 - + %1 Make Collateral Inputs %1 Make Collateral Inputs 396 - + %1 Create Denominations %1 Create Denominations 398 - + %1 Send %1 Send 400 - + watch-only watch-only 420 - + (n/a) (n/a) - 437 + 438 - + (no label) (no label) - 668 + 669 - + Transaction status. Hover over this field to show number of confirmations. Transaction status. Hover over this field to show number of confirmations. - 707 + 708 - + Date and time that the transaction was received. Date and time that the transaction was received. - 709 + 710 - + Type of transaction. Type of transaction. - 711 + 712 - + Whether or not a watch-only address is involved in this transaction. Whether or not a watch-only address is involved in this transaction. - 713 + 714 - + User-defined intent/purpose of the transaction. User-defined intent/purpose of the transaction. - 715 + 716 - + Amount removed from or added to balance. Amount removed from or added to balance. - 717 + 718 - + All All 67 80 - + Today Today 68 - + This week This week 69 - + This month This month 70 - + Last month Last month 71 - + This year This year 72 - + Range... Range... 73 - + Most Common Most Common 81 - + Received with Received with 82 - + Sent to Sent to 84 - + %1 Send %1 Send 86 - + %1 Make Collateral Inputs %1 Make Collateral Inputs 87 - + %1 Create Denominations %1 Create Denominations 88 - + %1 Mixing %1 Mixing 89 - + %1 Collateral Payment %1 Collateral Payment 90 - + To yourself To yourself 91 - + Mined Mined 92 - + Other Other 93 - + Enter address, transaction id, or label to search Enter address, transaction id, or label to search 99 - + Min amount Min amount 104 - + Abandon transaction Abandon transaction 150 - + Resend transaction 151 - + Copy address Copy address 152 - + Copy label Copy label 153 - + Copy amount Copy amount 154 - + Copy transaction ID Copy transaction ID 155 - + Copy raw transaction Copy raw transaction 156 - + Copy full transaction details Copy full transaction details 157 - + Edit address label Edit address label 158 - + Show transaction details Show transaction details 159 - + Show address QR code Show address QR code 160 - + Export Transaction History Export Transaction History 384 - + Comma separated file (*.csv) Comma separated file (*.csv) 385 - + Confirmed Confirmed 394 - + Watch-only Watch-only 396 - + Date Date 397 - + Type Type 398 - + Label Label 399 - + Address Address 400 - + ID ID 402 - + Exporting Failed Exporting Failed 405 - + There was an error trying to save the transaction history to %1. There was an error trying to save the transaction history to %1. 405 - + Exporting Successful Exporting Successful 409 - + The transaction history was successfully saved to %1. The transaction history was successfully saved to %1. 409 - + QR code QR code 569 - + Range: Range: 612 - + to to 621 @@ -5415,21 +5444,28 @@ https://www.transifex.com/projects/p/dash/ - - No wallet has been loaded. - No wallet has been loaded. - 29 + + No wallet has been loaded. +Go to File > Open Wallet to load a wallet. +- OR - + + 38 + + + Create a new wallet + Create a new wallet + 43 - + Send Coins Send Coins 244 - + default wallet default wallet 604 @@ -5438,1206 +5474,1226 @@ https://www.transifex.com/projects/p/dash/ - + &Export &Export 48 - + Export the data in the current tab to a file Export the data in the current tab to a file 49 - + Selected amount: Selected amount: 55 - + Backup Wallet Backup Wallet - 344 + 320 - + Wallet Data (*.dat) Wallet Data (*.dat) - 345 + 321 - + Backup Failed Backup Failed - 351 + 327 - + There was an error trying to save the wallet data to %1. There was an error trying to save the wallet data to %1. - 351 + 327 - + Backup Successful Backup Successful - 355 + 331 - + The wallet data was successfully saved to %1. The wallet data was successfully saved to %1. - 355 + 331 - + Cancel Cancel - 408 + 384 - + Error: Listening for incoming connections failed (listen returned error %s) Error: Listening for incoming connections failed (listen returned error %s) 41 - + Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee. Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee. 47 - + 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 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 85 - + This is a pre-release test build - use at your own risk - do not use for mining or merchant applications This is a pre-release test build - use at your own risk - do not use for mining or merchant applications 89 - + Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. 114 - + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. 117 - + Already have that input. Already have that input. 138 - + Cannot downgrade wallet Cannot downgrade wallet 143 - + Collateral not valid. Collateral not valid. 148 - + Corrupted block database detected Corrupted block database detected 151 - + Do you want to rebuild the block database now? Do you want to rebuild the block database now? 155 - + Done loading Done loading 156 - + Entries are full. Entries are full. 158 - + Error initializing block database Error initializing block database 160 - + Error initializing wallet database environment %s! Error initializing wallet database environment %s! 161 - + Error loading block database Error loading block database 167 - + Error opening block database Error opening block database - 169 + 168 - + Error reading from database, shutting down. Error reading from database, shutting down. - 170 + 169 - + Failed to listen on any port. Use -listen=0 if you want this. Failed to listen on any port. Use -listen=0 if you want this. - 186 + 184 - + -maxtxfee is set very high! Fees this large could be paid on a single transaction. -maxtxfee is set very high! Fees this large could be paid on a single transaction. 22 - + Cannot provide specific connections and have addrman find outgoing connections at the same. Cannot provide specific connections and have addrman find outgoing connections at the same. 30 - + Found unconfirmed denominated outputs, will wait till they confirm to continue. Found unconfirmed denominated outputs, will wait till they confirm to continue. 50 - + Invalid -socketevents ('%s') specified. Only these modes are supported: %s Invalid -socketevents ('%s') specified. Only these modes are supported: %s 56 - + Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions) Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions) 58 - + + SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported + + 75 + + Transaction index can't be disabled with governance validation enabled. Either start with -disablegovernance command line switch or enable transaction index. Transaction index can't be disabled with governance validation enabled. Either start with -disablegovernance command line switch or enable transaction index. 100 - + Can't mix: no compatible inputs found! Can't mix: no compatible inputs found! 142 - + Entry exceeds maximum size. Entry exceeds maximum size. 159 - + Found enough users, signing ( waiting %s ) Found enough users, signing ( waiting %s ) - 193 + 192 - + Found enough users, signing ... Found enough users, signing ... - 194 + 193 - + Importing... Importing... 195 - + Incompatible mode. Incompatible mode. 196 - + Incompatible version. Incompatible version. 197 - + Incorrect or no genesis block found. Wrong datadir for network? Incorrect or no genesis block found. Wrong datadir for network? 199 - + Input is not valid. Input is not valid. 201 - + Insufficient funds. Insufficient funds. 203 - + Invalid amount for -discardfee=<amount>: '%s' Invalid amount for -discardfee=<amount>: '%s' 208 - + Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) 210 - + Invalid minimum number of spork signers specified with -minsporkkeys Invalid minimum number of spork signers specified with -minsporkkeys 212 - + Keypool ran out, please call keypoolrefill first Keypool ran out, please call keypoolrefill first 216 - + Loading banlist... Loading banlist... 220 - + Loading fulfilled requests cache... Loading fulfilled requests cache... 222 - + Loading masternode cache... Loading masternode cache... 224 - + Lock is already in place. Lock is already in place. 228 - + Mixing in progress... Mixing in progress... 232 - + Need to specify a port with -whitebind: '%s' Need to specify a port with -whitebind: '%s' 233 - + No Masternodes detected. No Masternodes detected. 234 - + No compatible Masternode found. No compatible Masternode found. 235 - + Not enough funds to mix. Not enough funds to mix. 240 - + Not in the Masternode list. Not in the Masternode list. 241 - + Submitted to masternode, waiting in queue %s Submitted to masternode, waiting in queue %s - 259 + 263 - + Synchronization finished Synchronization finished - 260 + 264 - + Unable to start HTTP server. See debug log for details. Unable to start HTTP server. See debug log for details. - 287 + 291 - + Unknown response. Unknown response. - 290 + 294 - + User Agent comment (%s) contains unsafe characters. User Agent comment (%s) contains unsafe characters. - 295 + 299 - + Verifying wallet(s)... Verifying wallet(s)... - 297 + 301 - + Will retry... Will retry... - 305 + 309 - + Can't find random Masternode. Can't find random Masternode. 140 - + %s can't be lower than %s %s can't be lower than %s 126 - + %s is idle. %s is idle. 128 - + Can't mix while sync in progress. Can't mix while sync in progress. 141 - + Invalid netmask specified in -whitelist: '%s' Invalid netmask specified in -whitelist: '%s' 213 - + Invalid script detected. Invalid script detected. 214 - + %s file contains all private keys from this wallet. Do not share it with anyone! %s file contains all private keys from this wallet. Do not share it with anyone! 16 - + Failed to create backup, file already exists! This could happen if you restarted wallet in less than 60 seconds. You can continue if you are ok with this. Failed to create backup, file already exists! This could happen if you restarted wallet in less than 60 seconds. You can continue if you are ok with this. 43 - + Make sure to encrypt your wallet and delete all non-encrypted backups after you have verified that the wallet works! Make sure to encrypt your wallet and delete all non-encrypted backups after you have verified that the wallet works! 61 - + Prune configured below the minimum of %d MiB. Please use a higher number. Prune configured below the minimum of %d MiB. Please use a higher number. 70 - + Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) 72 - - Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. - Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. - 75 - - + The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct 78 - + The transaction amount is too small to send after the fee has been deducted The transaction amount is too small to send after the fee has been deducted 83 - + Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. 97 - + WARNING! Failed to replenish keypool, please unlock your wallet to do so. WARNING! Failed to replenish keypool, please unlock your wallet to do so. 107 - + Wallet is locked, can't replenish keypool! Automatic backups and mixing are disabled, please unlock your wallet to replenish keypool. Wallet is locked, can't replenish keypool! Automatic backups and mixing are disabled, please unlock your wallet to replenish keypool. 109 - + You need to rebuild the database using -reindex to change -timestampindex You need to rebuild the database using -reindex to change -timestampindex 120 - + You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain 122 - + %s failed %s failed 127 - + -maxmempool must be at least %d MB -maxmempool must be at least %d MB 134 - + Automatic backups disabled Automatic backups disabled 139 - + Cannot set -peerblockfilters without -blockfilterindex. Cannot set -peerblockfilters without -blockfilterindex. 145 - + Config setting for %s only applied on %s network when in [%s] section. Config setting for %s only applied on %s network when in [%s] section. 149 - + Could not find asmap file %s Could not find asmap file %s 152 - + Could not parse asmap file %s Could not parse asmap file %s 153 - + ERROR! Failed to create automatic backup ERROR! Failed to create automatic backup 157 - + Error loading %s: Private keys can only be disabled during creation Error loading %s: Private keys can only be disabled during creation 163 - + Error upgrading evo database Error upgrading evo database - 172 - - - Error: A fatal internal error occurred, see debug.log for details - Error: A fatal internal error occurred, see debug.log for details - 173 - - - Error: Disk space is low for %s - Error: Disk space is low for %s - 174 - - - Error: failed to add socket to epollfd (epoll_ctl returned error %s) - Error: failed to add socket to epollfd (epoll_ctl returned error %s) - 175 - - - Exceeded max tries. - Exceeded max tries. - 177 - - - Failed to commit EvoDB - Failed to commit EvoDB - 181 - - - Failed to create backup %s! - Failed to create backup %s! - 182 - - - Failed to create backup, error: %s - Failed to create backup, error: %s - 183 - - - Failed to delete backup, error: %s - Failed to delete backup, error: %s - 184 - - - Failed to rescan the wallet during initialization - Failed to rescan the wallet during initialization - 191 + 171 + Error: Disk space is low for %s + Error: Disk space is low for %s + 172 + + + Error: failed to add socket to epollfd (epoll_ctl returned error %s) + Error: failed to add socket to epollfd (epoll_ctl returned error %s) + 173 + + + Exceeded max tries. + Exceeded max tries. + 175 + + + Failed to commit EvoDB + Failed to commit EvoDB + 179 + + + Failed to create backup %s! + Failed to create backup %s! + 180 + + + Failed to create backup, error: %s + Failed to create backup, error: %s + 181 + + + Failed to delete backup, error: %s + Failed to delete backup, error: %s + 182 + + + Failed to rescan the wallet during initialization + Failed to rescan the wallet during initialization + 189 + + + Failed to verify database + + 191 + + + Ignoring duplicate -wallet %s. + + 194 + + Invalid P2P permission: '%s' Invalid P2P permission: '%s' 206 - + Invalid amount for -fallbackfee=<amount>: '%s' Invalid amount for -fallbackfee=<amount>: '%s' 209 - + Invalid masternodeblsprivkey. Please see documentation. Invalid masternodeblsprivkey. Please see documentation. 211 - + Loading block index... Loading block index... 221 - + Loading governance cache... Loading governance cache... 223 - + Loading sporks cache... Loading sporks cache... 225 - + Loading wallet... (%3.2f %%) Loading wallet... (%3.2f %%) 226 - + Loading wallet... Loading wallet... 227 - + Masternode queue is full. Masternode queue is full. 229 - + Masternode: Masternode: 230 - + Missing input transaction information. Missing input transaction information. 231 - + No errors detected. No errors detected. 236 - + No matching denominations found for mixing. No matching denominations found for mixing. 237 - + Not compatible with existing transactions. Not compatible with existing transactions. 238 - + Not enough file descriptors available. Not enough file descriptors available. 239 - + Prune cannot be configured with a negative value. Prune cannot be configured with a negative value. 242 - + Prune mode is incompatible with -blockfilterindex. Prune mode is incompatible with -blockfilterindex. 243 - + Prune mode is incompatible with -disablegovernance=false. Prune mode is incompatible with -disablegovernance=false. 244 - + Prune mode is incompatible with -txindex. Prune mode is incompatible with -txindex. 245 - + Pruning blockstore... Pruning blockstore... 246 - - Section [%s] is not recognized. - Section [%s] is not recognized. + + SQLiteDatabase: Failed to execute statement to verify database: %s + 250 - - Specified -walletdir "%s" does not exist - Specified -walletdir "%s" does not exist + + SQLiteDatabase: Failed to prepare statement to verify database: %s + + 251 + + + SQLiteDatabase: Failed to read database verification error: %s + + 252 + + + SQLiteDatabase: Unexpected application id. Expected %u, got %u + + 253 + + + Section [%s] is not recognized. + Section [%s] is not recognized. 254 - + + Specified -walletdir "%s" does not exist + Specified -walletdir "%s" does not exist + 258 + + Specified -walletdir "%s" is a relative path Specified -walletdir "%s" is a relative path - 255 + 259 - + Specified -walletdir "%s" is not a directory Specified -walletdir "%s" is not a directory - 256 + 260 - + Synchronizing blockchain... Synchronizing blockchain... - 261 + 265 - + The specified config file %s does not exist The specified config file %s does not exist - 264 - - - The wallet will avoid paying less than the minimum relay fee. - The wallet will avoid paying less than the minimum relay fee. - 266 - - - This is expected because you are running a pruned node. - This is expected because you are running a pruned node. - 267 - - - This is the minimum transaction fee you pay on every transaction. - This is the minimum transaction fee you pay on every transaction. - 269 - - - This is the transaction fee you will pay if you send a transaction. - This is the transaction fee you will pay if you send a transaction. - 270 - - - Transaction amounts must not be negative - Transaction amounts must not be negative - 272 - - - Transaction has too long of a mempool chain - Transaction has too long of a mempool chain - 275 - - - Transaction must have at least one recipient - Transaction must have at least one recipient - 276 - - - Transaction too large - Transaction too large - 278 - - - Trying to connect... - Trying to connect... - 279 - - - Unable to bind to %s on this computer. %s is probably already running. - Unable to bind to %s on this computer. %s is probably already running. - 281 - - - Unable to create the PID file '%s': %s - Unable to create the PID file '%s': %s - 282 - - - Unable to generate initial keys - Unable to generate initial keys - 283 - - - Unknown -blockfilterindex value %s. - Unknown -blockfilterindex value %s. - 288 - - - Upgrading UTXO database - Upgrading UTXO database - 293 + 268 - Wallet needed to be rewritten: restart %s to complete - Wallet needed to be rewritten: restart %s to complete - 300 + The wallet will avoid paying less than the minimum relay fee. + The wallet will avoid paying less than the minimum relay fee. + 270 - Warning: unknown new rules activated (versionbit %i) - Warning: unknown new rules activated (versionbit %i) - 303 + This is expected because you are running a pruned node. + This is expected because you are running a pruned node. + 271 - Wasn't able to create wallet backup folder %s! - Wasn't able to create wallet backup folder %s! - 304 + This is the minimum transaction fee you pay on every transaction. + This is the minimum transaction fee you pay on every transaction. + 273 - You can not start a masternode with wallet enabled. - You can not start a masternode with wallet enabled. - 308 + This is the transaction fee you will pay if you send a transaction. + This is the transaction fee you will pay if you send a transaction. + 274 - You need to rebuild the database using -reindex to change -addressindex - You need to rebuild the database using -reindex to change -addressindex - 309 + Transaction amounts must not be negative + Transaction amounts must not be negative + 276 - You need to rebuild the database using -reindex to change -spentindex - You need to rebuild the database using -reindex to change -spentindex - 310 + Transaction has too long of a mempool chain + Transaction has too long of a mempool chain + 279 - no mixing available. - no mixing available. - 312 + Transaction must have at least one recipient + Transaction must have at least one recipient + 280 - see debug.log for details. - see debug.log for details. - 313 + Transaction too large + Transaction too large + 282 + Trying to connect... + Trying to connect... + 283 + + + Unable to bind to %s on this computer. %s is probably already running. + Unable to bind to %s on this computer. %s is probably already running. + 285 + + + Unable to create the PID file '%s': %s + Unable to create the PID file '%s': %s + 286 + + + Unable to generate initial keys + Unable to generate initial keys + 287 + + + Unknown -blockfilterindex value %s. + Unknown -blockfilterindex value %s. + 292 + + + Upgrading UTXO database + Upgrading UTXO database + 297 + + + Wallet needed to be rewritten: restart %s to complete + Wallet needed to be rewritten: restart %s to complete + 304 + + + Warning: unknown new rules activated (versionbit %i) + Warning: unknown new rules activated (versionbit %i) + 307 + + + Wasn't able to create wallet backup folder %s! + Wasn't able to create wallet backup folder %s! + 308 + + + You can not start a masternode with wallet enabled. + You can not start a masternode with wallet enabled. + 312 + + + You need to rebuild the database using -reindex to change -addressindex + You need to rebuild the database using -reindex to change -addressindex + 313 + + + You need to rebuild the database using -reindex to change -spentindex + You need to rebuild the database using -reindex to change -spentindex + 314 + + + no mixing available. + no mixing available. + 316 + + + see debug.log for details. + see debug.log for details. + 317 + + The %s developers The %s developers 12 - + %s uses exact denominated amounts to send funds, you might simply need to mix some more coins. %s uses exact denominated amounts to send funds, you might simply need to mix some more coins. 19 - + Cannot obtain a lock on data directory %s. %s is probably already running. Cannot obtain a lock on data directory %s. %s is probably already running. 28 - + Distributed under the MIT software license, see the accompanying file %s or %s Distributed under the MIT software license, see the accompanying file %s or %s 33 - + Error loading %s: You can't enable HD on an already existing non-HD wallet Error loading %s: You can't enable HD on an already existing non-HD wallet 36 - + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. 38 - + Incorrect or no devnet genesis block found. Wrong datadir for devnet specified? Incorrect or no devnet genesis block found. Wrong datadir for devnet specified? 53 - + Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. 64 - + Please contribute if you find %s useful. Visit %s for further information about the software. Please contribute if you find %s useful. Visit %s for further information about the software. 67 - + This is the transaction fee you may discard if change is smaller than dust at this level This is the transaction fee you may discard if change is smaller than dust at this level 92 - + This is the transaction fee you may pay when fee estimates are not available. This is the transaction fee you may pay when fee estimates are not available. 95 - + Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate. Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate. 104 - + Warning: Private keys detected in wallet {%s} with disabled private keys Warning: Private keys detected in wallet {%s} with disabled private keys 112 - + %d of last 100 blocks have unexpected version %d of last 100 blocks have unexpected version 125 - + %s is not a valid backup folder! %s is not a valid backup folder! 129 - + %s is only allowed with a single wallet file %s is only allowed with a single wallet file 130 - + %s is set very high! %s is set very high! 131 - + %s request incomplete: %s request incomplete: 132 - + -devnet can only be specified once -devnet can only be specified once 133 - + -port must be specified when -devnet and -listen are specified -port must be specified when -devnet and -listen are specified 135 - + -rpcport must be specified when -devnet and -server are specified -rpcport must be specified when -devnet and -server are specified 136 - + A fatal internal error occurred, see debug.log for details A fatal internal error occurred, see debug.log for details 137 - + Cannot resolve -%s address: '%s' Cannot resolve -%s address: '%s' 144 - + Cannot write to data directory '%s'; check permissions. Cannot write to data directory '%s'; check permissions. 146 - + Change index out of range Change index out of range 147 - + Copyright (C) Copyright (C) 150 - + Disk space is too low! Disk space is too low! 154 - + Error loading %s Error loading %s 162 - + Error loading %s: Wallet corrupted Error loading %s: Wallet corrupted 164 - + Error loading %s: Wallet requires newer version of %s Error loading %s: Wallet requires newer version of %s 165 - + Error loading %s: You can't disable HD on an already existing HD wallet Error loading %s: You can't disable HD on an already existing HD wallet 166 - - Error loading wallet %s. Duplicate -wallet filename specified. - Error loading wallet %s. Duplicate -wallet filename specified. - 168 - - + Error upgrading chainstate database Error upgrading chainstate database - 171 + 170 - + Error: failed to add socket to kqueuefd (kevent returned error %s) Error: failed to add socket to kqueuefd (kevent returned error %s) - 176 + 174 - + Failed to clear fulfilled requests cache at %s Failed to clear fulfilled requests cache at %s - 178 + 176 - + Failed to clear governance cache at %s Failed to clear governance cache at %s - 179 + 177 - + Failed to clear masternode cache at %s Failed to clear masternode cache at %s - 180 + 178 - + Failed to find mixing queue to join Failed to find mixing queue to join - 185 + 183 - + Failed to load fulfilled requests cache from %s Failed to load fulfilled requests cache from %s - 187 + 185 - + Failed to load governance cache from %s Failed to load governance cache from %s - 188 + 186 - + Failed to load masternode cache from %s Failed to load masternode cache from %s - 189 + 187 - + Failed to load sporks cache from %s Failed to load sporks cache from %s - 190 + 188 - + Failed to start a new mixing queue Failed to start a new mixing queue - 192 + 190 - + Incorrect -rescan mode, falling back to default value Incorrect -rescan mode, falling back to default value 198 - + Initialization sanity check failed. %s is shutting down. Initialization sanity check failed. %s is shutting down. 200 - + Inputs vs outputs size mismatch. Inputs vs outputs size mismatch. 202 - + Invalid -onion address or hostname: '%s' Invalid -onion address or hostname: '%s' 204 - + Invalid -proxy address or hostname: '%s' Invalid -proxy address or hostname: '%s' 205 - + Invalid amount for -%s=<amount>: '%s' Invalid amount for -%s=<amount>: '%s' 207 - + Invalid spork address specified with -sporkaddr Invalid spork address specified with -sporkaddr 215 - + Loading P2P addresses... Loading P2P addresses... 219 - + Reducing -maxconnections from %d to %d, because of system limitations. Reducing -maxconnections from %d to %d, because of system limitations. 247 - + Replaying blocks... Replaying blocks... 248 - + Rescanning... Rescanning... 249 - + Session not complete! Session not complete! - 251 + 255 - + Session timed out. Session timed out. - 252 + 256 - + Signing transaction failed Signing transaction failed - 253 - - - Specified blocks directory "%s" does not exist. - Specified blocks directory "%s" does not exist. 257 - + + Specified blocks directory "%s" does not exist. + Specified blocks directory "%s" does not exist. + 261 + + Last queue was created too recently. Last queue was created too recently. 217 - + %s corrupt. Try using the wallet tool dash-wallet to salvage or restoring a backup. %s corrupt. Try using the wallet tool dash-wallet to salvage or restoring a backup. 13 - + Can't generate a change-address key. No keys in the internal keypool and can't generate any keys. Can't generate a change-address key. No keys in the internal keypool and can't generate any keys. 25 - + Last successful action was too recent. Last successful action was too recent. 218 - + Starting network threads... Starting network threads... - 258 - - - Synchronizing governance objects... - Synchronizing governance objects... 262 - - The source code is available from %s. - The source code is available from %s. - 263 - - - The transaction amount is too small to pay the fee - The transaction amount is too small to pay the fee - 265 - - - This is experimental software. - This is experimental software. - 268 - - - Transaction amount too small - Transaction amount too small - 271 - - - Transaction created successfully. - Transaction created successfully. - 273 - - - Transaction fees are too high. - Transaction fees are too high. - 274 - - - Transaction not valid. - Transaction not valid. - 277 - - - Unable to bind to %s on this computer (bind returned error %s) - Unable to bind to %s on this computer (bind returned error %s) - 280 - - - Unable to locate enough mixed funds for this transaction. - Unable to locate enough mixed funds for this transaction. - 284 - - - Unable to locate enough non-denominated funds for this transaction. - Unable to locate enough non-denominated funds for this transaction. - 285 - - - Unable to sign spork message, wrong key? - Unable to sign spork message, wrong key? - 286 - - - Unknown network specified in -onlynet: '%s' - Unknown network specified in -onlynet: '%s' - 289 - - Unknown state: id = %u - Unknown state: id = %u - 291 + Synchronizing governance objects... + Synchronizing governance objects... + 266 - Unsupported logging category %s=%s. - Unsupported logging category %s=%s. - 292 + The source code is available from %s. + The source code is available from %s. + 267 - Upgrading txindex database - Upgrading txindex database - 294 + The transaction amount is too small to pay the fee + The transaction amount is too small to pay the fee + 269 - Verifying blocks... - Verifying blocks... - 296 + This is experimental software. + This is experimental software. + 272 - Very low number of keys left: %d - Very low number of keys left: %d - 298 + Transaction amount too small + Transaction amount too small + 275 - Wallet is locked. - Wallet is locked. - 299 + Transaction created successfully. + Transaction created successfully. + 277 - Warning: can't use %s and %s together, will prefer %s - Warning: can't use %s and %s together, will prefer %s - 301 + Transaction fees are too high. + Transaction fees are too high. + 278 - Warning: incorrect parameter %s, path must exist! Using default path. - Warning: incorrect parameter %s, path must exist! Using default path. - 302 + Transaction not valid. + Transaction not valid. + 281 - You are starting with governance validation disabled. - You are starting with governance validation disabled. - 306 + Unable to bind to %s on this computer (bind returned error %s) + Unable to bind to %s on this computer (bind returned error %s) + 284 - You can not disable governance validation on a masternode. - You can not disable governance validation on a masternode. - 307 + Unable to locate enough mixed funds for this transaction. + Unable to locate enough mixed funds for this transaction. + 288 + Unable to locate enough non-denominated funds for this transaction. + Unable to locate enough non-denominated funds for this transaction. + 289 + + + Unable to sign spork message, wrong key? + Unable to sign spork message, wrong key? + 290 + + + Unknown network specified in -onlynet: '%s' + Unknown network specified in -onlynet: '%s' + 293 + + + Unknown state: id = %u + Unknown state: id = %u + 295 + + + Unsupported logging category %s=%s. + Unsupported logging category %s=%s. + 296 + + + Upgrading txindex database + Upgrading txindex database + 298 + + + Verifying blocks... + Verifying blocks... + 300 + + + Very low number of keys left: %d + Very low number of keys left: %d + 302 + + + Wallet is locked. + Wallet is locked. + 303 + + + Warning: can't use %s and %s together, will prefer %s + Warning: can't use %s and %s together, will prefer %s + 305 + + + Warning: incorrect parameter %s, path must exist! Using default path. + Warning: incorrect parameter %s, path must exist! Using default path. + 306 + + + You are starting with governance validation disabled. + You are starting with governance validation disabled. + 310 + + + You can not disable governance validation on a masternode. + You can not disable governance validation on a masternode. + 311 + + Your entries added successfully. Your entries added successfully. - 311 + 315 diff --git a/src/qt/locale/dash_it.ts b/src/qt/locale/dash_it.ts index e8adfb1b63..02285248ae 100644 --- a/src/qt/locale/dash_it.ts +++ b/src/qt/locale/dash_it.ts @@ -115,7 +115,9 @@ There was an error trying to save the address list to %1. Please try again. - C'é stato un errore mentre si salvava la lista degli indirizzi a %1. Per favore riprovare nuovamente. + An error message. + %1 is a name of the file (e.g., "addrbook.csv") that the bitcoin addresses were exported to. + C'é stato un errore durante il tentativo di salvare la lista degli indirizzi a %1. Per favore riprovare nuovamente. @@ -515,10 +517,6 @@ &Debug console &Console di Debug - - Open debugging console - Apri la console di Debug - &Network Monitor &Monitor di rete @@ -571,10 +569,6 @@ Open &URI... Apri &URI... - - Open a dash: URI or payment request - Apri un dash: URI o una richiesta di pagamento - &Command-line options Opzioni riga di &comando @@ -609,6 +603,14 @@ Show information about %1 Mostra informazioni %1 + + Open debugging and diagnostic console + Aprire la console di debug e diagnostica + + + Open a dash: URI + Apri un dash: URI + Create Wallet... Crea portafoglio... @@ -647,7 +649,7 @@ %n active connection(s) to Dash network - %n connessione attiva alla rete Dash%n connessioni attive alla rete Dash + %n connessione attiva alla rete Dash%n connessioni attive alla rete Dash%n connessioni attive alla rete Dash Network activity disabled @@ -679,7 +681,7 @@ Processed %n block(s) of transaction history. - Elaborati %n blocchi della cronologia delle transazioni.Elaborati %n blocchi della cronologia delle transazioni. + Elaborati %n blocchi della cronologia delle transazioni.Elaborati %n blocchi della cronologia delle transazioni.Elaborati %n blocchi della cronologia delle transazioni. %1 behind @@ -1150,8 +1152,8 @@ Elenco filtri: - Filter propsal list - Filtra l'elenco delle proposte + Filter proposal list + Filtra l'elenco delle proposal Proposal Count: @@ -1290,6 +1292,10 @@ Service Assistenza + + Type + Scrivi + PoSe Score Punteggio PoSe @@ -1425,6 +1431,10 @@ Hide Nascondi + + Dash Core is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain. + Dash Core è attualmente in fase di sincronizzazione. Scaricherà le intestazioni e i blocchi dai peers e li convaliderà fino a raggiungere la punta della blockchain. + Unknown. Syncing Headers (%1, %2%)... Sconosciuto. Sincronizzazione intestazioni (%1, %2%)... @@ -1436,22 +1446,10 @@ Open URI Apri URI - - Open payment request from URI or file - Apri richiesta di pagamento da URI o file - URI: URI: - - Select payment request file - Seleziona il file di richiesta di pagamento - - - Select payment request file to open - Seleziona il file di richiesta di pagamento da aprire - OpenWalletActivity @@ -1518,6 +1516,14 @@ MiB MiB + + Whether to keep the specified custom change address or not. + Indica se mantenere o meno l'indirizzo di modifica personalizzato specificato. + + + Keep custom change &address + Mantieni la modifica personalizzata &address + Show additional tab listing all your masternodes in first sub-tab<br/>and all masternodes on the network in second sub-tab. Mostra la tabella aggiuntiva che elenca tutti i Masternode nella prima sotto-tabella <br/>e tutti i Masternode sulla rete nella seconda sotto-tabella. @@ -1590,10 +1596,6 @@ Automatically open the Dash Core client port on the router. This only works when your router supports UPnP and it is enabled. Apri automaticamente la porta utilizzata dal client Dash Core nel router. Funziona solo se il router supporta UPnP ed è attivato. - - Automatically open the Bitcoin client port on the router. This only works when your router supports NAT-PMP and it is enabled. The external port could be random. - Apri automaticamente la porta del client Bitcoin sul router. Funziona solo quando il router supporta NAT-PMP ed è abilitato. La porta esterna potrebbe essere casuale. - Map port using NA&T-PMP Mappa Porta utilizzando NA&T-PMP @@ -1682,6 +1684,10 @@ Map port using &UPnP Mappa le porte tramite &UPnP + + Automatically open the Dash Core client port on the router. This only works when your router supports NAT-PMP and it is enabled. The external port could be random. + Apri automaticamente la porta del client Dash Core sul router. Funziona solo quando il tuo router supporta NAT-PMP ed è abilitato. La porta esterna potrebbe essere casuale. + Proxy &IP: &IP del proxy: @@ -1933,7 +1939,7 @@ https://www.transifex.com/projects/p/dash/ %n Rounds - %n Round%n Rounds + %n Round%n Rounds%n Rounds Found enough compatible inputs to mix %1 @@ -1961,7 +1967,7 @@ https://www.transifex.com/projects/p/dash/ Denominated inputs have %5 of %n rounds on average - Gli input denominati hanno in media %5 di %n round Gli input denominati hanno in media %5 di %n round + Gli input denominati hanno in media %5 di %n round Gli input denominati hanno in media %5 di %n round Gli input denominati hanno in media %5 di %n round keys left: %1 @@ -2047,12 +2053,12 @@ https://www.transifex.com/projects/p/dash/ "dash: //" non è un URI valido. Utilizza "dash:". - Payment request fetch URL is invalid: %1 - URL di recupero della Richiesta di pagamento non valido: %1 + Cannot process payment request as BIP70 is no longer supported. + Impossibile elaborare la richiesta di pagamento in quanto BIP70 non è più supportato. - Cannot process payment request because BIP70 support was not compiled in. - Impossibile elaborare la richiesta di pagamento perché il supporto BIP70 non è stato compilato. + Due to discontinued support, you should request the merchant to provide you with a BIP21 compatible URI or use a wallet that does continue to support BIP70. + A causa dell'interruzione del supporto, dovresti richiedere al commerciante di fornirti un URI compatibile con BIP21 o utilizzare un portafoglio che continui a supportare BIP70. Invalid payment address %1 @@ -2066,66 +2072,6 @@ https://www.transifex.com/projects/p/dash/ Payment request file handling Gestione del file di richiesta del pagamento - - Payment request file cannot be read! This can be caused by an invalid payment request file. - Il file di richiesta del pagamento non può essere letto! Il file in questione potrebbe essere non valido. - - - Payment request rejected - Richiesta di pagamento rifiutata - - - Payment request network doesn't match client network. - La rete della richiesta di pagamento non coincide con la rete del cliente. - - - Payment request expired. - Richiesta di pagamento scaduta. - - - Payment request is not initialized. - La richiesta di pagamento non è stata inizializzata - - - Unverified payment requests to custom payment scripts are unsupported. - Le richieste di pagamento non verificate verso script di pagamento personalizzati non sono supportate. - - - Invalid payment request. - Richiesta di pagamento invalida - - - Requested payment amount of %1 is too small (considered dust). - L'importo di pagamento richiesto di %1 è troppo basso (considerato come infinitesimale). - - - Refund from %1 - Rimborso da %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Il pagamento richiesto %1 é troppo grande (%2 bytes, permesso %3 bytes). - - - Error communicating with %1: %2 - Errore di comunicazione con %1: %2 - - - Payment request cannot be parsed! - La richiesta di pagamento non può essere analizzata o processata! - - - Bad response from server %1 - Risposta errata da parte del server %1 - - - Network request error - Errore di richiesta di rete - - - Payment acknowledged - Pagamento riconosciuto - PeerTableModel @@ -2238,10 +2184,6 @@ https://www.transifex.com/projects/p/dash/ Reset all settings changed in the GUI Reimposta tutti i campi dell'interfaccia grafica - - Set SSL root certificates for payment request (default: -system-) - Imposta i certificati root SSL per le richieste di pagamento (default: -system-) - Show splash screen on startup (default: %u) Mostra schermata iniziale all'avvio (default: %u) @@ -2258,6 +2200,10 @@ https://www.transifex.com/projects/p/dash/ Error: %1 Errore: %1 + + Error initializing settings: %1 + Errore durante l'inizializzazione delle impostazioni: %1 + Error: Failed to load application fonts. Errore:Impossibile caricare i caratteri dell'applicazione @@ -2340,27 +2286,27 @@ https://www.transifex.com/projects/p/dash/ %n second(s) - %n secondo%n secondi + %n secondo%n secondi%n secondi %n minute(s) - %n minuto%n minuti + %n minuto%n minuti%n minuti %n hour(s) - %n ora%n ore + %n ora%n ore%n ore %n day(s) - %n giorno%n giorni + %n giorno%n giorni%n giorni %n week(s) - %n settimana%n settimane + %n settimana%n settimane%n settimane %n year(s) - %n anno%n anni + %n anno%n anni%n anni %1 and %2 @@ -2401,29 +2347,6 @@ https://www.transifex.com/projects/p/dash/ &Save Image... &Salva Immagine - - Error creating QR Code. - Errore di generazione del QR Code - - - - QRGeneralImageWidget - - &Save Image... - &Salva Immagine - - - &Copy Image - &Copia Immagine - - - Save QR Code - Salva codice QR - - - PNG Image (*.png) - Immagine PNG (*.png) - QRImageWidget @@ -2606,10 +2529,6 @@ https://www.transifex.com/projects/p/dash/ -rescan=2: Rescan the block chain for missing wallet transactions starting from genesis block. -rescan=2: Riesamina la catena di blocchi per le transazioni del portafoglio mancanti a partire dal blocco genesis. - - Wallet Path - Percorso del Portafoglio - User Agent User Agent @@ -2722,26 +2641,10 @@ https://www.transifex.com/projects/p/dash/ &Wallet Repair &Riparare Portafoglio - - Recover transactions 1 - Ristabilire le transazioni 1 - - - Recover transactions 2 - Ristabilire le transazioni 2 - Upgrade wallet format Aggiorna il formato del portafoglio - - -zapwallettxes=1: Recover transactions from blockchain (keep meta-data, e.g. account owner). - -zapwallettxes=1: Recupera transazioni dalla blockchain (mantiene i meta-data, es. il propietario del conto) - - - -zapwallettxes=2: Recover transactions from blockchain (drop meta-data). - -zapwallettxes=2: Recupera transazioni dalla blockchain (non conserva i meta-data) - -upgradewallet: Upgrade wallet to latest format on startup. (Note: this is NOT an update of the wallet itself!) -aggiornaportafoglio: Aggiorna il portafoglio all'ultima versione in startup. (Nota: questo NON é un aggiornamento del portafoglio stesso!) @@ -2850,6 +2753,10 @@ https://www.transifex.com/projects/p/dash/ Outbound In uscita + + Outbound block-relay + Block-relay in uscita + Yes Si @@ -2893,6 +2800,10 @@ https://www.transifex.com/projects/p/dash/ An optional message to attach to the payment request, which will be displayed when the request is opened.<br>Note: The message will not be sent with the payment over the Dash network. Messaggio facoltativo da allegare alla richiesta di pagamento, che verrà visualizzato all'apertura della richiesta.<br> Nota: il messaggio non verrà inviato con il pagamento sulla rete di Dash. + + An optional label to associate with the new receiving address (used by you to identify an invoice). It is also attached to the payment request. + Un'etichetta facoltativa da associare al nuovo indirizzo di ricezione (da te utilizzata per identificare una fattura). È inoltre allegato alla richiesta di pagamento. + Use this form to request payments. All fields are <b>optional</b>. Usa questo modulo per richiedere pagamenti. Tutti i campi sono <b>opzionali</b>. @@ -3118,6 +3029,14 @@ https://www.transifex.com/projects/p/dash/ Choose... Scegli... + + When there is less transaction volume than space in the blocks, miners as well as relaying nodes may enforce a minimum fee. Paying only this minimum fee is just fine, but be aware that this can result in a never confirming transaction once there is more demand for dash transactions than the network can process. + Quando il volume delle transazioni è inferiore allo spazio nei blocchi, i miner e i nodi di inoltro possono applicare una commissione minima. Pagare solo questa tariffa minima va bene, ma tieni presente che ciò può comportare una transazione mai confermata una volta che c'è più richiesta di transazioni precipitose di quanto la rete possa elaborare. + + + A too low fee might result in a never confirming transaction (read the tooltip) + Una commissione troppo bassa potrebbe comportare una transazione mai confermata (leggi il tooltip) + Confirmation time target: Obiettivo del tempo di conferma: @@ -3126,10 +3045,6 @@ https://www.transifex.com/projects/p/dash/ If the custom fee is set to 1000 duffs and the transaction is only 250 bytes, then "per kilobyte" only pays 250 duffs in fee,<br />while "at least" pays 1000 duffs. For transactions bigger than a kilobyte both pay by kilobyte. Se la tariffa personalizzata è impostata su 1000 duff e la transazione è di soli 250 byte, paga solo 250 duff "per kilobyte" di Fee, <br />mentre paga "almeno" 1000 duff. Per le transazioni più grandi di un kilobyte pagate entrambi per kilobyte. - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks.<br />But be aware that this can end up in a never confirming transaction once there is more demand for dash transactions than the network can process. - Pagare solo la commissione minima va bene finché il volume di transazioni è minore rispetto allo spazio nei blocchi. <br />Ma sii consapevole che questo potrebbe risultare in una transazione non confermata, una volta che ci fosse più richiesta di transazioni di Dash di quanto la rete possa elaborare. - per kilobyte per kilobyte @@ -3150,10 +3065,6 @@ https://www.transifex.com/projects/p/dash/ Hide Nascondi - - (read the tooltip) - (leggi il suggerimento) - Recommended: Raccomandato @@ -3226,10 +3137,6 @@ https://www.transifex.com/projects/p/dash/ %1 (%2 blocks) %1 (%2 bloccare) - - from wallet %1 - dal wallet %1 - using utilizzando @@ -3254,6 +3161,30 @@ https://www.transifex.com/projects/p/dash/ Confirm the %1 send action Conferma l'azione di invio %1 + + Cr&eate Unsigned + Cr&eate Non firmato + + + Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet. + Crea una Transazione Bitcoin con Firma Parziale (PSBT) da utilizzare ad es. con un portafoglio %1 offline o con un portafoglio hardware compatibile con PSBT. + + + from wallet '%1' + Dal wallet '%1' + + + %1 to '%2' + %1 a '%2' + + + Do you want to draft this transaction? + Vuoi la bozza di questa transazione? + + + This will produce a Partially Signed Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet. + Questo produrrà una transazione con Firma Parziale (PSBT) che puoi copiare e quindi firmare con, ad es., un portafoglio %1 offline o con un portafoglio hardware compatibile con PSBT. + %1 funds only Solo fondi %1 @@ -3280,7 +3211,7 @@ https://www.transifex.com/projects/p/dash/ This transaction will consume %n input(s) - Questa transazione consumerà %n inputQuesta transazione consumerà %n input + Questa transazione consumerà %n inputQuesta transazione consumerà %n inputQuesta transazione consumerà %n input Warning: Using %1 with %2 or more inputs can harm your privacy and is not recommended @@ -3298,10 +3229,30 @@ https://www.transifex.com/projects/p/dash/ or oppure + + To review recipient list click "Show Details..." + Per rivedere l'elenco dei destinatari facendo clic su "Mostra dettagli..." + Confirm send coins Conferma l'invio di dash + + Confirm transaction proposal + Conferma la proposta di transazione + + + Copy PSBT to clipboard + Copia PSBT negli appunti + + + Send + Invia + + + PSBT copied + PSBT copiata + The recipient address is not valid. Please recheck. L'indirizzo del destinatario non è valido. Si prega di ricontrollare. @@ -3334,13 +3285,9 @@ https://www.transifex.com/projects/p/dash/ Payment request expired. Richiesta di pagamento scaduta. - - Pay only the required fee of %1 - Paga solo la commissione richiesta di %1 - Estimated to begin confirmation within %n block(s). - Inizio della confirmazione stimato in %n bloccoInizio del processo di conferma stimato in %n blocchi + Inizio della confirmazione stimato in %n bloccoInizio del processo di conferma stimato in %n blocchiInizio del processo di conferma stimato in %n blocchi Warning: Invalid Dash address @@ -3445,17 +3392,6 @@ https://www.transifex.com/projects/p/dash/ Memo: Memo: - - Enter a label for this address to add it to your address book - Inserisci un'etichetta per questo indirizzo, per aggiungerlo nella rubrica - - - - SendConfirmationDialog - - Send - Manda - ShutdownWindow @@ -3657,7 +3593,7 @@ https://www.transifex.com/projects/p/dash/ TransactionDesc Open for %n more block(s) - Aperto per %n blocco in piúAperto per %n blocchi in piú + Aperto per %n blocco in piúAperto per %n blocchi in piúAperto per %n blocchi in piú Open until %1 @@ -3745,7 +3681,7 @@ https://www.transifex.com/projects/p/dash/ matures in %n more block(s) - Matura in %n blocco in piúMatura in %n blocchi in piú + Matura in %n blocco in piúMatura in %n blocchi in piúMatura in %n blocchi in piú not accepted @@ -3791,14 +3727,6 @@ https://www.transifex.com/projects/p/dash/ Transaction total size Dimensione totale della transazione - - (Certificate was not verified) - (Il Certificato non è stato verificato) - - - Merchant - Negoziante - Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. È necessario attendere %1 blocchi prima che le monete generate possano essere spese. Quando è stato generato questo blocco, è stato trasmesso alla rete in modo da poter essere aggiunto alla blockchain. Se l'inserimento avrà esito negativo il suo stato sarà modificato in "non accettato" e risulterà non spendibile. Questo può occasionalmente accadere se un altro nodo genera un blocco entro pochi secondi dal tuo. @@ -3855,7 +3783,7 @@ https://www.transifex.com/projects/p/dash/ Open for %n more block(s) - Aperto per %n blocco in piúAperto per %n blocchi in piú + Aperto per %n blocco in piúAperto per %n blocchi in piúAperto per %n blocchi in piú Open until %1 @@ -4064,6 +3992,10 @@ https://www.transifex.com/projects/p/dash/ Abandon transaction Abbandona transazione + + Resend transaction + Invia nuovamente la transazione + Copy address Copia l'indirizzo @@ -4190,8 +4122,16 @@ https://www.transifex.com/projects/p/dash/ WalletFrame - No wallet has been loaded. - Non è stato caricato alcun portafoglio. + No wallet has been loaded. +Go to File > Open Wallet to load a wallet. +- OR - + Nessun portafoglio è stato caricato. +Vai su File > Apri Wallet per caricare un Wallet. +- Oppure - + + + Create a new wallet + Crea un nuovo Wallet @@ -4346,6 +4286,10 @@ https://www.transifex.com/projects/p/dash/ Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions) Importo non valido per -maxtxfee=<amount>: '%s' (deve essere almeno pari alla commissione 'minrelay fee' di %s per prevenire transazioni bloccate) + + SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported + SQLiteDatabase: schema del wallet sqlite alla versione sconosciuta %d. È supportata solo la versione %d + Transaction index can't be disabled with governance validation enabled. Either start with -disablegovernance command line switch or enable transaction index. L'indice di transazione non può essere disabilitato con la convalida della governance abilitata. Inizia con l'opzione della riga di comando -disablegovernance o abilita l'indice delle transazioni. @@ -4518,10 +4462,6 @@ https://www.transifex.com/projects/p/dash/ Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) Prune: l'ultima sincronizzazione del portafoglio risulta essere oltre la riduzione dei dati. È necessario eseguire un -reindex (scaricare nuovamente la blockchain in caso di nodo pruned) - - Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. - Non è possibile un Rescan in modalità pruned. Sarà necessario utilizzare -reindex che farà scaricare nuovamente tutta la blockchain. - The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct Il database dei blocchi contiene un blocco che sembra provenire dal futuro. Questo può essere dovuto alla data e ora del tuo computer impostate in modo scorretto. Ricostruisci il database dei blocchi se sei certo che la data e l'ora sul tuo computer siano corrette @@ -4590,10 +4530,6 @@ https://www.transifex.com/projects/p/dash/ Error upgrading evo database Errore durante l'aggiornamento del database evo - - Error: A fatal internal error occurred, see debug.log for details - Errore: si è presentato un errore interno fatale, consulta il file debug.log per maggiori dettagli - Error: Disk space is low for %s Errore: lo spazio su disco è insufficiente per %s @@ -4626,6 +4562,14 @@ https://www.transifex.com/projects/p/dash/ Failed to rescan the wallet during initialization Impossibile eseguire nuovamente la scansione del portafoglio durante l'inizializzazione + + Failed to verify database + Impossibile verificare il database + + + Ignoring duplicate -wallet %s. + Duplicato -wallet %s ignorato. + Invalid P2P permission: '%s' Autorizzazione P2P non valida: '%s' @@ -4706,6 +4650,22 @@ https://www.transifex.com/projects/p/dash/ Pruning blockstore... Pruning del blockstore... + + SQLiteDatabase: Failed to execute statement to verify database: %s + SQLiteDatabase: Impossibile eseguire l'istruzione per verificare il database: %s + + + SQLiteDatabase: Failed to prepare statement to verify database: %s + SQLiteDatabase: Impossibile preparare l'istruzione per verificare il database: %s + + + SQLiteDatabase: Failed to read database verification error: %s + SQLiteDatabase: Impossibile leggere l'errore di verifica del database: %s + + + SQLiteDatabase: Unexpected application id. Expected %u, got %u + SQLiteDatabase: ID applicazione imprevisto. Previsto %u, ottenuto %u + Section [%s] is not recognized. La sezione [%s] non è riconosciuta. @@ -4864,10 +4824,6 @@ https://www.transifex.com/projects/p/dash/ This is the transaction fee you may pay when fee estimates are not available. Questo è il costo di transazione che potresti pagare quando le stime della fee non sono disponibili. - - This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. - Questo prodotto include software sviluppato dal progetto OpenSSL per l'uso del Toolkit OpenSSL %s, software crittografico scritto da Eric Young e software UPnP scritto da Thomas Bernard. - Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate. Impossibile riprodurre i blocchi. Dovrai ricostruire il database usando -reindex-chainstate. @@ -4948,10 +4904,6 @@ https://www.transifex.com/projects/p/dash/ Error loading %s: You can't disable HD on an already existing HD wallet Errore durante il caricamento di %s: non è possibile disabilitare l'HD su un portafoglio HD già esistente - - Error loading wallet %s. Duplicate -wallet filename specified. - Errore durante il caricamento del portafoglio%s. Il Nome -wallet filename specificato è duplicato - Error upgrading chainstate database Errore durante l'aggiornamento del database chainstate @@ -5172,9 +5124,5 @@ https://www.transifex.com/projects/p/dash/ Your entries added successfully. Le tue voci sono state aggiunte con successo. - - Zapping all transactions from wallet... - Cancella e ricompila tutte le transazioni dal wallet... - \ No newline at end of file diff --git a/src/qt/locale/dash_pl.ts b/src/qt/locale/dash_pl.ts index 4649cda2d3..e0639c9e7d 100644 --- a/src/qt/locale/dash_pl.ts +++ b/src/qt/locale/dash_pl.ts @@ -115,6 +115,8 @@ There was an error trying to save the address list to %1. Please try again. + An error message. + %1 is a name of the file (e.g., "addrbook.csv") that the bitcoin addresses were exported to. Wystąpił błąd podczas próby zapisu listy adresów do %1. Spróbuj ponownie. @@ -515,10 +517,6 @@ &Debug console Konsola &debugowania - - Open debugging console - Otwórz konsolę debugowania - &Network Monitor Mo&nitor Sieci @@ -571,10 +569,6 @@ Open &URI... Otwórz &URI... - - Open a dash: URI or payment request - Otwórz dash: Link lub żądanie zapłaty - &Command-line options &Opcje konsoli @@ -609,6 +603,14 @@ Show information about %1 Pokaż informacje o %1 + + Open debugging and diagnostic console + Otwórz debugowanie i konsolę diagnostyczną + + + Open a dash: URI + Otwórz dash: URI + Create Wallet... Stwórz Portfel... @@ -1150,7 +1152,7 @@ Filtruj listę: - Filter propsal list + Filter proposal list Filtruj listę wniosków @@ -1290,6 +1292,10 @@ Service Usługa + + Type + Typ + PoSe Score Wynik PoSe @@ -1436,22 +1442,10 @@ Open URI Otwórz URI: - - Open payment request from URI or file - Otwórz żądanie zapłaty z URI lub pliku - URI: URI: - - Select payment request file - Otwórz żądanie zapłaty z pliku - - - Select payment request file to open - Wybierz plik żądania zapłaty do otwarcia - OpenWalletActivity @@ -1590,10 +1584,6 @@ Automatically open the Dash Core client port on the router. This only works when your router supports UPnP and it is enabled. Automatycznie otwórz port klienta Dash Core na ruterze. Opcja działa jedynie, jeżeli router obsługuje UPnP i funkcja UPnP jest włączona. - - Automatically open the Bitcoin client port on the router. This only works when your router supports NAT-PMP and it is enabled. The external port could be random. - Automatycznie otwórz port klienta Bitcoina na routerze. Działa to tylko wtedy, gdy router obsługuje NAT-PMP i jest włączony. Port zewnętrzny może być losowy. - Map port using NA&T-PMP Mapuj port za pomocą NA&T-PMP @@ -2046,14 +2036,6 @@ https://www.transifex.com/projects/p/dash/ 'dash://' is not a valid URI. Use 'dash:' instead. 'Dash: //' nie jest prawidłowym identyfikatorem URI. Zamiast tego użyj 'Dash:'. - - Payment request fetch URL is invalid: %1 - Żądanie płatności podowduje że URL jest niewłaściwy: %1 - - - Cannot process payment request because BIP70 support was not compiled in. - Nie można przetworzyć żądania płatności, ponieważ obsługa BIP70 nie została wkompilowana. - Invalid payment address %1 Nieprawidłowy adres płatności %1 @@ -2066,66 +2048,6 @@ https://www.transifex.com/projects/p/dash/ Payment request file handling Obsługa pliku z żądaniem płatności - - Payment request file cannot be read! This can be caused by an invalid payment request file. - Nie można odczytać pliku z żądaniem płatności! Może to być spowodowane przez niewłaściwy plik z żądaniem płatności. - - - Payment request rejected - Żądanie płatności zostało odrzucone - - - Payment request network doesn't match client network. - Sieć żądania płatnośc nie pasuje do sieci klienta. - - - Payment request expired. - Żądanie płatności wygasło. - - - Payment request is not initialized. - Żądanie płatności nie zostało zainicjonowane. - - - Unverified payment requests to custom payment scripts are unsupported. - Niezweryfikowane żądania płatności dla specjalnych skryptów z płatnościami nie są obsługiwane. - - - Invalid payment request. - Nieważne żądanie płatności. - - - Requested payment amount of %1 is too small (considered dust). - Żądana kwota %1 jest za niska (uznana za pył). - - - Refund from %1 - Zwrot z %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Żądanie płatności %1 jest zbyt duże (%2 bitów, maksymalny rozmiar to %3 bitów). - - - Error communicating with %1: %2 - Błąd komunikacji z %1 : %2 - - - Payment request cannot be parsed! - Żądanie płatności nie może zostać przeanalizowane! - - - Bad response from server %1 - Błędna odpowiedź z serwera %1 - - - Network request error - Błąd żądania sieci - - - Payment acknowledged - Płatność potwierdzona - PeerTableModel @@ -2238,10 +2160,6 @@ https://www.transifex.com/projects/p/dash/ Reset all settings changed in the GUI Resetuj wszystkie ustawienia zmienione w graficznym interfejsie użytkownika - - Set SSL root certificates for payment request (default: -system-) - Ustaw główne cerytfikaty SSL dla żądań płatności (domyślnie: -system-) - Show splash screen on startup (default: %u) Przy uruchamianiu pokaż ekran powitalny (domyślnie: %u) @@ -2401,29 +2319,6 @@ https://www.transifex.com/projects/p/dash/ &Save Image... &Zapisz obraz... - - Error creating QR Code. - Błąd kreowania kodu QR. - - - - QRGeneralImageWidget - - &Save Image... - &Zapisz obraz... - - - &Copy Image - &Kopiuj obraz - - - Save QR Code - Zapisz Kod QR - - - PNG Image (*.png) - Obraz PNG (*.png) - QRImageWidget @@ -2606,10 +2501,6 @@ https://www.transifex.com/projects/p/dash/ -rescan=2: Rescan the block chain for missing wallet transactions starting from genesis block. -rescan = 2: Skanuj ponownie łańcuch bloków w poszukiwaniu brakujących transakcji portfela, zaczynając od bloku Genesis. - - Wallet Path - Ścieżka portfela - User Agent Agent użytkownika @@ -2722,26 +2613,10 @@ https://www.transifex.com/projects/p/dash/ &Wallet Repair &Naprawa portfela - - Recover transactions 1 - Odzyskaj transakcję 1 - - - Recover transactions 2 - Odzyskaj transakcję 2 - Upgrade wallet format Uaktualnij format portfela - - -zapwallettxes=1: Recover transactions from blockchain (keep meta-data, e.g. account owner). - -zapwallettxes=1: Odzyskaj transakcje z łańcucha bloków (nie zmieniaj meta-danych, np. właściciela konta). - - - -zapwallettxes=2: Recover transactions from blockchain (drop meta-data). - -zapwallettxes=2: Odzyskaj transakcje z blockchainu (pozbądź się meta-danych) - -upgradewallet: Upgrade wallet to latest format on startup. (Note: this is NOT an update of the wallet itself!) -upgradewallet: przeprowadź upgrade portfela do najnowszego formatu podczas uruchomienia. (Nie oznacza to zaktualizowania samego portfela!) @@ -3126,10 +3001,6 @@ https://www.transifex.com/projects/p/dash/ If the custom fee is set to 1000 duffs and the transaction is only 250 bytes, then "per kilobyte" only pays 250 duffs in fee,<br />while "at least" pays 1000 duffs. For transactions bigger than a kilobyte both pay by kilobyte. Jeśli ręcznie ustalona opłata wynosi 1000 Duffów, a sama transakcja ma tylko 250 bajtów, to opłata "za kilobajt" wynosi tylko 250 duffów. <br/>Dzieje się tak dla każdej transakcji poniżej 1000 duffów. W przypadku transakcji większych niż jeden kilobajt opłata jest naliczana od kilobajta. - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks.<br />But be aware that this can end up in a never confirming transaction once there is more demand for dash transactions than the network can process. - Uiszczanie minimalnej opłaty za transakcję jest ok, dopóki ilość transakcji nie przekracza dostępnego miejsca w bloku. <br />Jeśli zostanie wysłanych więcej transakcji niż sieć może przetworzyć, to może się zdarzyć, że Twoja transakcja nigdy nie zostanie potwierdzona. - per kilobyte na kilobajt @@ -3150,10 +3021,6 @@ https://www.transifex.com/projects/p/dash/ Hide Ukryj - - (read the tooltip) - (przeczytaj podpowiedź w chmurce) - Recommended: Polecany: @@ -3226,10 +3093,6 @@ https://www.transifex.com/projects/p/dash/ %1 (%2 blocks) %1 (%2 bloki) - - from wallet %1 - z portfela %1 - using używając @@ -3334,10 +3197,6 @@ https://www.transifex.com/projects/p/dash/ Payment request expired. Żądanie płatności wygasło. - - Pay only the required fee of %1 - Uiść jedynie minimalną opłatę %1 - Estimated to begin confirmation within %n block(s). Potwierdzenia zaczną się za około %n blokPotwierdzenia zaczną się za około %n blokiPotwierdzenia zaczną się za około %n blokówPotwierdzenia zaczną się za około %n bloków @@ -3445,17 +3304,6 @@ https://www.transifex.com/projects/p/dash/ Memo: Notatka: - - Enter a label for this address to add it to your address book - Wprowadź etykietę dla tego adresu by dodać go do książki adresowej - - - - SendConfirmationDialog - - Send - Wyślij - ShutdownWindow @@ -3791,14 +3639,6 @@ https://www.transifex.com/projects/p/dash/ Transaction total size Całkowity rozmiar transakcji - - (Certificate was not verified) - (Certyfikat nie został zweryfikowany) - - - Merchant - Kupiec - Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. Wygenerowane monety muszą dojrzeć przez %1 bloków zanim będzie można je wysłać. Gdy wygenerowałeś ten blok, został on ogłoszony w sieci i dodany do łańcucha bloków. Jeżeli nie uda mu się wejść do łańcucha, jego status zostanie zmieniony na "nie zaakceptowano" i nie będzie można go wydać. To czasem zdarza się, gdy inny węzeł wygeneruje blok kilka sekund przed tobą. @@ -4189,11 +4029,7 @@ https://www.transifex.com/projects/p/dash/ WalletFrame - - No wallet has been loaded. - Nie załadowano żadnego portfela. - - + WalletModel @@ -4518,10 +4354,6 @@ https://www.transifex.com/projects/p/dash/ Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) Oczyszczanie: ostatnia synchronizacja portfela sięga poza skasowane dane. Użyj -reindex (w razie oczyszczenia węzła, ponownie pobierz cały łańcuch bloków). - - Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. - Ponownie skanowanie jest niemożliwe w trybie oczyszczania. Użyj -reindex, co spowoduje ponowne pobranie całego łańcucha bloków. - The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct Baza danych bloków zawiera blok, który zdaje się pochodzić z przyszłości. Taka sytuacja może się zdarzyć, jeżeli zegar Twojego komputera pokazuje niepoprawną datę i godzinę. Przebuduj bazę danych bloków wyłącznie, jeżeli masz pewność, że zegar Twojego komputera pokazuje poprawną datę i godzinę. @@ -4590,10 +4422,6 @@ https://www.transifex.com/projects/p/dash/ Error upgrading evo database Wystąpił błąd podczas ulepszania bazy danych evo. - - Error: A fatal internal error occurred, see debug.log for details - Błąd: Wystąpił wewnętrzny błąd krytyczny, szczegóły znajdziesz w pliku debug.log - Error: Disk space is low for %s Błąd: Nie ma wystarczająco miejsca na dysku dla %s @@ -4864,10 +4692,6 @@ https://www.transifex.com/projects/p/dash/ This is the transaction fee you may pay when fee estimates are not available. To jest prawdopodobny koszt transakcj jeśli szacunki opłat są niedostępne. - - This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. - Produkt zawiera oprogramowanie stworzone przez OpenSSL Project do użycia w OpensSSL Toolkit %s, oprogramowanie kryptograficzne napisane przez Eric Young oraz oprogramowanie UPnP napisane przez Thomas Bernard. - Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate. Nie można odtworzyć bloków. Będziesz musiał odbudować bazę danych przy użyciu -reindex-chainstate. @@ -4948,10 +4772,6 @@ https://www.transifex.com/projects/p/dash/ Error loading %s: You can't disable HD on an already existing HD wallet Błąd podczas wczytywania %s: Niemożliwe jest zmienienie porfela HD w standarodowy porfel. - - Error loading wallet %s. Duplicate -wallet filename specified. - Błąd ładowania portfela %s. Podano zduplikowaną nazwę pliku -wallet. - Error upgrading chainstate database Błąd ładowania bazy bloków @@ -5172,9 +4992,5 @@ https://www.transifex.com/projects/p/dash/ Your entries added successfully. Twoje wejścia zostały dodane z powodzeniem. - - Zapping all transactions from wallet... - Zappowanie wszystkich transakcji z portfela - \ No newline at end of file diff --git a/src/qt/locale/dash_ru.ts b/src/qt/locale/dash_ru.ts index 4d04c53276..f6c9c74b1d 100644 --- a/src/qt/locale/dash_ru.ts +++ b/src/qt/locale/dash_ru.ts @@ -115,6 +115,8 @@ There was an error trying to save the address list to %1. Please try again. + An error message. + %1 is a name of the file (e.g., "addrbook.csv") that the bitcoin addresses were exported to. Произошла ошибка при сохранении адресной книги в %1. Пожалуйста, попробуйте еще раз. @@ -515,10 +517,6 @@ &Debug console &Консоль отладки - - Open debugging console - Открыть консоль отладки - &Network Monitor &Монитор сети @@ -571,10 +569,6 @@ Open &URI... Открыть &URI... - - Open a dash: URI or payment request - Открыть dash: URI или запрос платежа - &Command-line options &Параметры командной строки @@ -609,6 +603,14 @@ Show information about %1 Показать информацию о %1 + + Open debugging and diagnostic console + Открыть консоль отладки и диагностики + + + Open a dash: URI + Открыть dash: URI + Create Wallet... Создать кошелёк... @@ -1150,7 +1152,7 @@ Фильтровать список: - Filter propsal list + Filter proposal list Фильтровать список предложений @@ -1290,6 +1292,10 @@ Service Сервис + + Type + Тип + PoSe Score PoSe штраф @@ -1425,6 +1431,10 @@ Hide Скрыть + + Dash Core is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain. + Dash Core синхронизируется. Он будет скачивать заголовки и блоки и проверять их, пока не достигнет вершины цепочки блоков. + Unknown. Syncing Headers (%1, %2%)... Неизвестно. Синхронизация заголовков (%1, %2%)... @@ -1436,22 +1446,10 @@ Open URI Открыть URI - - Open payment request from URI or file - Открыть запрос платежа из URI или файла - URI: URI: - - Select payment request file - Выбрать файл запроса платежа - - - Select payment request file to open - Выберите файл запроса платежа - OpenWalletActivity @@ -1518,6 +1516,14 @@ MiB MiB + + Whether to keep the specified custom change address or not. + Сохранять указанный свой адрес для сдачи или нет. + + + Keep custom change &address + Сохранить свой &адрес для сдачи + Show additional tab listing all your masternodes in first sub-tab<br/>and all masternodes on the network in second sub-tab. Показывать дополнительную вкладку со списком своих мастернод<br/>в одной таблице и списком всех мастернод в другой. @@ -1590,10 +1596,6 @@ Automatically open the Dash Core client port on the router. This only works when your router supports UPnP and it is enabled. Автоматически открыть порт для Dash Core на роутере. Работает только в том случае, если Ваш роутер поддерживает UPnP и данная функция включена. - - Automatically open the Bitcoin client port on the router. This only works when your router supports NAT-PMP and it is enabled. The external port could be random. - Автоматически открыть порт для Dash Core на роутере. Работает только в том случае, если Ваш роутер поддерживает NAT-PMP и данная функция включена. Внешний порт может быть любым. - Map port using NA&T-PMP Пробросить порт через NA&T-PMP @@ -1682,6 +1684,10 @@ Map port using &UPnP Пробросить порт через &UPnP + + Automatically open the Dash Core client port on the router. This only works when your router supports NAT-PMP and it is enabled. The external port could be random. + Автоматически открыть порт для Dash Core на роутере. Работает только в том случае, если Ваш роутер поддерживает NAT-PMP и данная функция включена. Внешний порт может быть любым. + Proxy &IP: &IP Прокси: @@ -2047,12 +2053,8 @@ https://www.transifex.com/projects/p/dash/ 'dash://' не является валидным URI. Используйте 'dash:'. - Payment request fetch URL is invalid: %1 - Неверный URL запроса платежа: %1 - - - Cannot process payment request because BIP70 support was not compiled in. - Невозможно обработать запрос платежа так как поддержка BIP70 была отключена. + Cannot process payment request as BIP70 is no longer supported. + Невозможно обработать запрос платежа так как BIP70 больше не поддерживается. Invalid payment address %1 @@ -2066,66 +2068,6 @@ https://www.transifex.com/projects/p/dash/ Payment request file handling Обработка файла запроса платежа - - Payment request file cannot be read! This can be caused by an invalid payment request file. - Не удается прочесть либо разобрать файл запроса платежа! Возможно это некоректный файл. - - - Payment request rejected - Запрос платежа отклонен - - - Payment request network doesn't match client network. - Сеть запроса платежа не соответствует сети клиента. - - - Payment request expired. - Время этого запроса платежа истекло. - - - Payment request is not initialized. - Запрос платежа не инициализирован. - - - Unverified payment requests to custom payment scripts are unsupported. - Непроверенные запросы платежей с нестандартными платёжными сценариями не поддерживаются. - - - Invalid payment request. - Неправильный запрос платежа. - - - Requested payment amount of %1 is too small (considered dust). - Запрошенная сумма платежа %1 слишком мала (считается "пылью"). - - - Refund from %1 - Возврат от %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Запрос платежа %1 слишком большой (%2 байт, разрешено %3 байт). - - - Error communicating with %1: %2 - Ошибка связи с %1: %2 - - - Payment request cannot be parsed! - Не могу разобрать запрос платежа! - - - Bad response from server %1 - Плохой ответ от сервера %1 - - - Network request error - Ошибка сетевого запроса - - - Payment acknowledged - Платёж принят - PeerTableModel @@ -2238,10 +2180,6 @@ https://www.transifex.com/projects/p/dash/ Reset all settings changed in the GUI Сбросить все настройки, измененные через графический интерфейс - - Set SSL root certificates for payment request (default: -system-) - Указать корневые SSL-сертификаты для запроса платежа (по умолчанию: -system-) - Show splash screen on startup (default: %u) Показывать заставку при запуске (по умолчанию: %u) @@ -2258,6 +2196,10 @@ https://www.transifex.com/projects/p/dash/ Error: %1 Ошибка: %1 + + Error initializing settings: %1 + Ошибка инициализации настроек: %1 + Error: Failed to load application fonts. Ошибка: не удалось загрузить шрифты приложения. @@ -2401,29 +2343,6 @@ https://www.transifex.com/projects/p/dash/ &Save Image... &Сохранить изображение... - - Error creating QR Code. - Ошибка создания QR-кода - - - - QRGeneralImageWidget - - &Save Image... - &Сохранить изображение... - - - &Copy Image - &Копировать изображение - - - Save QR Code - Сохранить QR-код - - - PNG Image (*.png) - Изображение PNG (*.png) - QRImageWidget @@ -2606,10 +2525,6 @@ https://www.transifex.com/projects/p/dash/ -rescan=2: Rescan the block chain for missing wallet transactions starting from genesis block. -rescan=2: Перепроверить цепочку блоков на предмет отсутствующих в кошельке транзакций, начиная с самого первого блока. - - Wallet Path - Путь к кошельку - User Agent User Agent @@ -2722,26 +2637,10 @@ https://www.transifex.com/projects/p/dash/ &Wallet Repair Ремонт &кошелька - - Recover transactions 1 - Восстановление транзакций 1 - - - Recover transactions 2 - Восстановление транзакций 2 - Upgrade wallet format Обновить формат кошелька - - -zapwallettxes=1: Recover transactions from blockchain (keep meta-data, e.g. account owner). - -zapwallettxes=1: Восстановить транзакции из цепочки блоков (сохранить мета-данные, например, о владельцах аккаунтов). - - - -zapwallettxes=2: Recover transactions from blockchain (drop meta-data). - -zapwallettxes=2: Восстановить транзакции из цепочки блоков (удалить мета-данные). - -upgradewallet: Upgrade wallet to latest format on startup. (Note: this is NOT an update of the wallet itself!) -upgradewallet: Обновить формат кошелька при следующем запуске. (Примечание: обновление непосредственно клиент кошелька НЕ выполняется!) @@ -3124,11 +3023,7 @@ https://www.transifex.com/projects/p/dash/ If the custom fee is set to 1000 duffs and the transaction is only 250 bytes, then "per kilobyte" only pays 250 duffs in fee,<br />while "at least" pays 1000 duffs. For transactions bigger than a kilobyte both pay by kilobyte. - Если ручная комиссия установлена в 1000 duff, а транзакция по размеру только 250 байт, то плата "за килобайт" составит лишь 250 duff,<br>в то время как "минимум" будет равна 1000 duff. Для транзакций больше килобайта в любом случае идет расчет "за килобайт". - - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks.<br />But be aware that this can end up in a never confirming transaction once there is more demand for dash transactions than the network can process. - Оплаты только минимальной комиссии должно быть достаточно во всех случаях, пока в блоках достаточно места.<br>Однако, будьте готовы к тому, что транзакция может вовсе не получить подтверждения,<br>если количество транзакций будет стабильно больше, чем сеть способна обработать. + Если ручная комиссия установлена в 1000 duff, а транзакция по размеру только 250 байт, то плата "за килобайт" составит лишь 250 duff,<br>в то время как "минимум" будет равна 1000 duff. Для транзакций больше килобайта в любом случае идет расчет "за килобайт". per kilobyte @@ -3150,10 +3045,6 @@ https://www.transifex.com/projects/p/dash/ Hide Скрыть - - (read the tooltip) - (прочтите всплывающую подсказку) - Recommended: Рекомендовано: @@ -3226,10 +3117,6 @@ https://www.transifex.com/projects/p/dash/ %1 (%2 blocks) %1 (блоков: %2) - - from wallet %1 - из кошелька %1 - using используя @@ -3254,6 +3141,14 @@ https://www.transifex.com/projects/p/dash/ Confirm the %1 send action Подтвердить отправку с помощью %1 + + from wallet '%1' + из кошелька '%1' + + + %1 to '%2' + %1 на '%2' + %1 funds only только средства %1 @@ -3302,6 +3197,10 @@ https://www.transifex.com/projects/p/dash/ Confirm send coins Подтвердите отправку монет + + Send + Отправить + The recipient address is not valid. Please recheck. Адрес получателя неверный. Пожалуйста, перепроверьте. @@ -3334,10 +3233,6 @@ https://www.transifex.com/projects/p/dash/ Payment request expired. Время этого запроса платежа истекло. - - Pay only the required fee of %1 - Заплатить только требуемую комиссию %1 - Estimated to begin confirmation within %n block(s). Будет подтверждено приблизительно в течение %n блока.Будет подтверждено приблизительно в течение %n блоков.Будет подтверждено приблизительно в течение %n блоков.Будет подтверждено приблизительно в течение %n блоков. @@ -3352,7 +3247,7 @@ https://www.transifex.com/projects/p/dash/ Confirm custom change address - Подтвердите адрес для сдачи + Подтвердите свой адрес для сдачи The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure? @@ -3445,17 +3340,6 @@ https://www.transifex.com/projects/p/dash/ Memo: Примечание: - - Enter a label for this address to add it to your address book - Введите метку для данного адреса для добавления его в адресную книгу - - - - SendConfirmationDialog - - Send - Отправить - ShutdownWindow @@ -3791,14 +3675,6 @@ https://www.transifex.com/projects/p/dash/ Transaction total size Полный размер транзакции - - (Certificate was not verified) - (Сертификат не был проверен) - - - Merchant - Продавец - Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. Сгенерированные монеты должны подождать %1 блоков, прежде чем они могут быть потрачены. Когда Вы сгенерировали этот блок, он был отправлен в сеть для добавления в цепочку блоков. Если он не попадёт в цепочку, его статус изменится на "не принят", и монеты будут недействительны. Это иногда происходит в случае, если другой узел сгенерирует блок на несколько секунд раньше вас. @@ -4064,6 +3940,10 @@ https://www.transifex.com/projects/p/dash/ Abandon transaction Сбросить транзакцию + + Resend transaction + Отправить транзакцию еще раз + Copy address Копировать адрес @@ -4190,8 +4070,8 @@ https://www.transifex.com/projects/p/dash/ WalletFrame - No wallet has been loaded. - Не был загружен ни один кошелёк. + Create a new wallet + Создать новый кошелёк @@ -4518,10 +4398,6 @@ https://www.transifex.com/projects/p/dash/ Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) Удаление блоков: последняя синхронизация кошелька выходит за рамки удаленных данных. Вам нужно запустить клиента с ключом -reindex (в случае узла с удаленными блоками это означает повторное скачивание всей цепи блоков) - - Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. - Повторное сканирование невозможно в режиме удаления блоков. Вам надо будет использовать -reindex, что приведет к повторной загрузке всей цепи блоков. - The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct База данных блоков содержит блок, созданный в будущем. Такое может случиться из-за некорректно установленных даты и времени на Вашем компьютере. Перестройте базу блоков, только если вы уверены, что дата и время корректны. @@ -4590,10 +4466,6 @@ https://www.transifex.com/projects/p/dash/ Error upgrading evo database Ошибка обновления базы данных evo - - Error: A fatal internal error occurred, see debug.log for details - Ошибка: Произошла критическая ошибка, подробности смотрите в файле debug.log - Error: Disk space is low for %s Ошибка: мало места на диске для %s @@ -4626,6 +4498,10 @@ https://www.transifex.com/projects/p/dash/ Failed to rescan the wallet during initialization Ошибка сканирования кошелька во время инициализации + + Failed to verify database + Ошибка проверки базы данных + Invalid P2P permission: '%s' Некорректные разрешения P2P : '%s' @@ -4864,10 +4740,6 @@ https://www.transifex.com/projects/p/dash/ This is the transaction fee you may pay when fee estimates are not available. Это комиссия, которую Вы заплатите при отправке транзакции, если расчет комиссии не доступен. - - This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. - Этот продукт включает ПО, разработанное проектом OpenSSL Project для использования в OpenSSL Toolkit %s, криптографическое ПО, написанное Eric Young и ПО для работы с UPnP, написанное Thomas Bernard. - Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate. Невозможно повторить блоки. Необходимо перестроить базы даных с помощью -reindex-chainstate. @@ -4948,10 +4820,6 @@ https://www.transifex.com/projects/p/dash/ Error loading %s: You can't disable HD on an already existing HD wallet Ошибка загрузки %s: Вы не можете отключить HD режим для существующего HD кошелька - - Error loading wallet %s. Duplicate -wallet filename specified. - Ошибка загрузки кошелька %s. Имя файла -wallet указано повторно. - Error upgrading chainstate database Ошибка обновления базы данных состояний цепочки @@ -5172,9 +5040,5 @@ https://www.transifex.com/projects/p/dash/ Your entries added successfully. Ваши записи успешно добавлены. - - Zapping all transactions from wallet... - Удаление всех транзакций из кошелька... - \ No newline at end of file From 1664246f77318551f52c29bfcf9dfc757135570e Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sun, 9 Apr 2023 08:09:18 +0300 Subject: [PATCH 56/63] fix(tests): a couple of fixes for dynamically_add/update functions (#5288) ## Issue being fixed or feature implemented should hopefully fix some sporadic ci test failures (like https://gitlab.com/dashpay/dash/-/jobs/4052206622#L1962) ## What was done? tweaked dynamically_add/update functions to make checks more consistent and avoid some edge cases, pls see individual commits ## How Has This Been Tested? `feature_llmq_hpmn.py` and `feature_dip3_v19.py` still work locally, let's see if ci is now (constantly) happy about these too... ## 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 - [x] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- test/functional/feature_dip3_v19.py | 12 ++-- test/functional/feature_llmq_hpmn.py | 56 +++++++++---------- .../test_framework/test_framework.py | 44 +++++++++------ 3 files changed, 63 insertions(+), 49 deletions(-) diff --git a/test/functional/feature_dip3_v19.py b/test/functional/feature_dip3_v19.py index a60b64901b..87a175610f 100755 --- a/test/functional/feature_dip3_v19.py +++ b/test/functional/feature_dip3_v19.py @@ -106,12 +106,16 @@ class DIP3V19Test(DashTestFramework): def test_revoke_protx(self, revoke_protx, revoke_keyoperator): funds_address = self.nodes[0].getnewaddress() - self.nodes[0].sendtoaddress(funds_address, 1) - self.nodes[0].generate(1) + fund_txid = self.nodes[0].sendtoaddress(funds_address, 1) + self.wait_for_instantlock(fund_txid, self.nodes[0]) + tip = self.nodes[0].generate(1)[0] + assert_equal(self.nodes[0].getrawtransaction(fund_txid, 1, tip)['confirmations'], 1) self.sync_all(self.nodes) - self.nodes[0].protx('revoke', revoke_protx, revoke_keyoperator, 1, funds_address) - self.nodes[0].generate(1) + protx_result = self.nodes[0].protx('revoke', revoke_protx, revoke_keyoperator, 1, funds_address) + self.wait_for_instantlock(protx_result, self.nodes[0]) + tip = self.nodes[0].generate(1)[0] + assert_equal(self.nodes[0].getrawtransaction(protx_result, 1, tip)['confirmations'], 1) self.sync_all(self.nodes) self.log.info(f"Succesfully revoked={revoke_protx}") for mn in self.mninfo: diff --git a/test/functional/feature_llmq_hpmn.py b/test/functional/feature_llmq_hpmn.py index 7abc4d95ad..24c85ddb1f 100755 --- a/test/functional/feature_llmq_hpmn.py +++ b/test/functional/feature_llmq_hpmn.py @@ -112,46 +112,48 @@ class LLMQHPMNTest(DashTestFramework): self.test_hpmn_protx_are_in_mnlist(hpmn_protxhash_list) self.log.info("Test that HPMNs are paid 4x blocks in a row") - self.test_hpmmn_payements(window_analysis=256) + self.test_hpmn_payments(window_analysis=256) self.log.info(self.nodes[0].masternodelist()) return - def test_hpmmn_payements(self, window_analysis): + def test_hpmn_payments(self, window_analysis): current_hpmn = None - consecutive_paymments = 0 + consecutive_payments = 0 for i in range(0, window_analysis): payee = self.get_mn_payee_for_block(self.nodes[0].getbestblockhash()) if payee is not None and payee.hpmn: if current_hpmn is not None and payee.proTxHash == current_hpmn.proTxHash: # same HPMN - assert consecutive_paymments > 0 - consecutive_paymments += 1 - consecutive_paymments_rpc = self.nodes[0].protx('info', current_hpmn.proTxHash)['state']['consecutivePayments'] - assert_equal(consecutive_paymments, consecutive_paymments_rpc) + assert consecutive_payments > 0 + consecutive_payments += 1 + consecutive_payments_rpc = self.nodes[0].protx('info', current_hpmn.proTxHash)['state']['consecutivePayments'] + assert_equal(consecutive_payments, consecutive_payments_rpc) else: # new HPMN if current_hpmn is not None: # make sure the old one was paid 4 times in a row - assert_equal(consecutive_paymments, 4) - consecutive_paymments_rpc = self.nodes[0].protx('info', current_hpmn.proTxHash)['state']['consecutivePayments'] + assert_equal(consecutive_payments, 4) + consecutive_payments_rpc = self.nodes[0].protx('info', current_hpmn.proTxHash)['state']['consecutivePayments'] # old HPMN should have its nConsecutivePayments reset to 0 - assert_equal(consecutive_paymments_rpc, 0) + assert_equal(consecutive_payments_rpc, 0) + consecutive_payments_rpc = self.nodes[0].protx('info', payee.proTxHash)['state']['consecutivePayments'] + # if hpmn is the one we start "for" loop with, + # we have no idea how many times it was paid before - rely on rpc results here + consecutive_payments = consecutive_payments_rpc if i == 0 and current_hpmn is None else 1 current_hpmn = payee - consecutive_paymments = 1 - consecutive_paymments_rpc = self.nodes[0].protx('info', current_hpmn.proTxHash)['state']['consecutivePayments'] - assert_equal(consecutive_paymments, consecutive_paymments_rpc) + assert_equal(consecutive_payments, consecutive_payments_rpc) else: # not a HPMN if current_hpmn is not None: # make sure the old one was paid 4 times in a row - assert_equal(consecutive_paymments, 4) - consecutive_paymments_rpc = self.nodes[0].protx('info', current_hpmn.proTxHash)['state']['consecutivePayments'] + assert_equal(consecutive_payments, 4) + consecutive_payments_rpc = self.nodes[0].protx('info', current_hpmn.proTxHash)['state']['consecutivePayments'] # old HPMN should have its nConsecutivePayments reset to 0 - assert_equal(consecutive_paymments_rpc, 0) + assert_equal(consecutive_payments_rpc, 0) current_hpmn = None - consecutive_paymments = 0 + consecutive_payments = 0 self.nodes[0].generate(1) if i % 8 == 0: @@ -199,14 +201,15 @@ class LLMQHPMNTest(DashTestFramework): reward_address = self.nodes[0].getnewaddress() collateral_amount = 4000 - collateral_txid = self.nodes[0].sendtoaddress(collateral_address, collateral_amount) - # send to same address to reserve some funds for fees - self.nodes[0].sendtoaddress(funds_address, 1) - collateral_vout = 0 - self.nodes[0].generate(1) + outputs = {collateral_address: collateral_amount, funds_address: 1} + collateral_txid = self.nodes[0].sendmany("", outputs) + self.wait_for_instantlock(collateral_txid, self.nodes[0]) + tip = self.nodes[0].generate(1)[0] self.sync_all(self.nodes) - rawtx = self.nodes[0].getrawtransaction(collateral_txid, 1) + rawtx = self.nodes[0].getrawtransaction(collateral_txid, 1, tip) + assert_equal(rawtx['confirmations'], 1) + collateral_vout = 0 for txout in rawtx['vout']: if txout['value'] == Decimal(collateral_amount): collateral_vout = txout['n'] @@ -216,15 +219,12 @@ class LLMQHPMNTest(DashTestFramework): ipAndPort = '127.0.0.1:%d' % p2p_port(len(self.nodes)) operatorReward = len(self.nodes) - self.nodes[0].generate(1) - - protx_success = False try: self.nodes[0].protx('register_hpmn', collateral_txid, collateral_vout, ipAndPort, owner_address, bls['public'], voting_address, operatorReward, reward_address, funds_address, True) - protx_success = True + # this should never succeed + assert False except: self.log.info("protx_hpmn rejected") - assert_equal(protx_success, False) def test_masternode_count(self, expected_mns_count, expected_hpmns_count): mn_count = self.nodes[0].masternode('count') diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 04a6c34b6b..1971431ef7 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -1068,8 +1068,11 @@ class DashTestFramework(BitcoinTestFramework): protx_success = True except: self.log.info("protx_hpmn rejected") + + assert_equal(protx_success, not should_be_rejected) + if should_be_rejected: - assert_equal(protx_success, False) + # nothing to do return self.dynamically_initialize_datadir(self.nodes[0].chain,node_p2p_port, node_rpc_port) @@ -1105,14 +1108,15 @@ class DashTestFramework(BitcoinTestFramework): platform_http_port = '%d' % (node_p2p_port + 102) if hpmn else '' collateral_amount = 4000 if hpmn else 1000 - collateral_txid = self.nodes[0].sendtoaddress(collateral_address, collateral_amount) - # send to same address to reserve some funds for fees - self.nodes[0].sendtoaddress(funds_address, 1) - collateral_vout = 0 - self.nodes[0].generate(1) + outputs = {collateral_address: collateral_amount, funds_address: 1} + collateral_txid = self.nodes[0].sendmany("", outputs) + self.wait_for_instantlock(collateral_txid, self.nodes[0]) + tip = self.nodes[0].generate(1)[0] self.sync_all(self.nodes) - rawtx = self.nodes[0].getrawtransaction(collateral_txid, 1) + rawtx = self.nodes[0].getrawtransaction(collateral_txid, 1, tip) + assert_equal(rawtx['confirmations'], 1) + collateral_vout = 0 for txout in rawtx['vout']: if txout['value'] == Decimal(collateral_amount): collateral_vout = txout['n'] @@ -1122,11 +1126,13 @@ class DashTestFramework(BitcoinTestFramework): ipAndPort = '127.0.0.1:%d' % node_p2p_port operatorReward = idx - self.nodes[0].generate(1) register_rpc = 'register_hpmn' if hpmn else 'register' protx_result = self.nodes[0].protx(register_rpc, collateral_txid, collateral_vout, ipAndPort, owner_address, bls['public'], voting_address, operatorReward, reward_address, platform_node_id, platform_p2p_port, platform_http_port, funds_address, True) - self.nodes[0].generate(1) + self.wait_for_instantlock(protx_result, self.nodes[0]) + tip = self.nodes[0].generate(1)[0] self.sync_all(self.nodes) + + assert_equal(self.nodes[0].getrawtransaction(protx_result, 1, tip)['confirmations'], 1) mn_info = MasternodeInfo(protx_result, owner_address, voting_address, bls['public'], bls['secret'], collateral_address, collateral_txid, collateral_vout, ipAndPort, hpmn) self.mninfo.append(mn_info) @@ -1139,26 +1145,30 @@ class DashTestFramework(BitcoinTestFramework): operator_reward_address = self.nodes[0].getnewaddress() # For the sake of the test, generate random nodeid, p2p and http platform values - r = rnd if rnd is not None else random.randint(1000, 65000) + r = rnd if rnd is not None else random.randint(21000, 65000) platform_node_id = hash160(b'%d' % r).hex() platform_p2p_port = '%d' % (r + 1) platform_http_port = '%d' % (r + 2) - self.nodes[0].sendtoaddress(funds_address, 1) - self.nodes[0].generate(1) + fund_txid = self.nodes[0].sendtoaddress(funds_address, 1) + self.wait_for_instantlock(fund_txid, self.nodes[0]) + tip = self.nodes[0].generate(1)[0] + assert_equal(self.nodes[0].getrawtransaction(fund_txid, 1, tip)['confirmations'], 1) self.sync_all(self.nodes) protx_success = False try: - self.nodes[0].protx('update_service_hpmn', hpmn_info.proTxHash, hpmn_info.addr, hpmn_info.keyOperator, platform_node_id, platform_p2p_port, platform_http_port, operator_reward_address, funds_address) - self.nodes[0].generate(1) + protx_result = self.nodes[0].protx('update_service_hpmn', hpmn_info.proTxHash, hpmn_info.addr, hpmn_info.keyOperator, platform_node_id, platform_p2p_port, platform_http_port, operator_reward_address, funds_address) + self.wait_for_instantlock(protx_result, self.nodes[0]) + tip = self.nodes[0].generate(1)[0] + assert_equal(self.nodes[0].getrawtransaction(protx_result, 1, tip)['confirmations'], 1) self.sync_all(self.nodes) self.log.info("Updated HPMN %s: platformNodeID=%s, platformP2PPort=%s, platformHTTPPort=%s" % (hpmn_info.proTxHash, platform_node_id, platform_p2p_port, platform_http_port)) protx_success = True except: self.log.info("protx_hpmn rejected") - if should_be_rejected: - assert_equal(protx_success, False) + + assert_equal(protx_success, not should_be_rejected) def prepare_masternodes(self): self.log.info("Preparing %d masternodes" % self.mn_count) @@ -1305,7 +1315,7 @@ class DashTestFramework(BitcoinTestFramework): self.start_node(0) self.import_deterministic_coinbase_privkeys() required_balance = HIGHPERFORMANCE_MASTERNODE_COLLATERAL * self.hpmn_count - required_balance += MASTERNODE_COLLATERAL * (self.mn_count - self.hpmn_count) + 1 + required_balance += MASTERNODE_COLLATERAL * (self.mn_count - self.hpmn_count) + 100 self.log.info("Generating %d coins" % required_balance) while self.nodes[0].getbalance() < required_balance: self.bump_mocktime(1) From fe1d7e083aa0a3e019a8bcd8a4d00e610cf8efc4 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 7 Apr 2023 18:08:37 +0300 Subject: [PATCH 57/63] fix(tests): Bumps in wait_for_tx/instantlock (#5301) ## Issue being fixed or feature implemented 1. we need to move time forward to let invs being relayed 2. nNextInvSend in SendMessages can be bumped up to 30+ seconds into the future in rare cases make sure timeouts in tests are high enough to relay tx inv/wait for corresponding islock ## What was done? tl;dr: bump mocktime while waiting, wait longer extracted fixes from https://github.com/dashpay/dash/pull/5288 but I expect this to fix other sporadic test failures too ## How Has This Been Tested? tests are ok locally and in https://github.com/dashpay/dash/pull/5288 ## 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 **For repository code-owners and collaborators only** - [ ] I have assigned this pull request to a milestone --- test/functional/test_framework/test_framework.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 1971431ef7..08b3615933 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -1407,13 +1407,14 @@ class DashTestFramework(BitcoinTestFramework): ret = {**decoded, **ret} return ret - def wait_for_tx(self, txid, node, expected=True, timeout=15): + def wait_for_tx(self, txid, node, expected=True, timeout=60): def check_tx(): try: + self.bump_mocktime(1) return node.getrawtransaction(txid) except: return False - if wait_until(check_tx, timeout=timeout, sleep=0.5, do_assert=expected) and not expected: + if wait_until(check_tx, timeout=timeout, sleep=1, do_assert=expected) and not expected: raise AssertionError("waiting unexpectedly succeeded") def create_islock(self, hextx, deterministic=False): @@ -1446,13 +1447,14 @@ class DashTestFramework(BitcoinTestFramework): return islock - def wait_for_instantlock(self, txid, node, expected=True, timeout=15): + def wait_for_instantlock(self, txid, node, expected=True, timeout=60): def check_instantlock(): + self.bump_mocktime(1) try: return node.getrawtransaction(txid, True)["instantlock"] except: return False - if wait_until(check_instantlock, timeout=timeout, sleep=0.5, do_assert=expected) and not expected: + if wait_until(check_instantlock, timeout=timeout, sleep=1, do_assert=expected) and not expected: raise AssertionError("waiting unexpectedly succeeded") def wait_for_chainlocked_block(self, node, block_hash, expected=True, timeout=15): From 1fd442f2293cb1f18026b0e97d67f7dc351ff439 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Sun, 9 Apr 2023 08:12:39 +0300 Subject: [PATCH 58/63] feat: min protocol version check for SML serialisation (#5302) ## Issue being fixed or feature implemented This was reported/requested by @HashEngineering: > Older versions of our App won't sync due to if (obj.nVersion == BASIC_BLS_VERSION) . Older versions don't know what version a SML Entry is. As such, they will never read the type field. On the android client this causes an offset problem when reading the mnlistdiff and it will throw an exception that bans the peer that supplied it. Soon enough, no peers will be left to connect to because they will all give the android client bad data. ## What was done? With this PR, SML will serialise the new v19 fields (`nType`, `platformHTTPPort`, `platformNodeID`) if the client's version is at least equal to `70227`. Note: Serialisation for hashing skips the above rule. Also, functional test mininode protocol version is set to `70227`. ## How Has This Been Tested? ## Breaking Changes ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [x] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation **For repository code-owners and collaborators only** - [x] I have assigned this pull request to a milestone --- src/evo/simplifiedmns.h | 3 +++ test/functional/test_framework/messages.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/evo/simplifiedmns.h b/src/evo/simplifiedmns.h index dd3882ca41..77165c56b6 100644 --- a/src/evo/simplifiedmns.h +++ b/src/evo/simplifiedmns.h @@ -73,6 +73,9 @@ public: obj.keyIDVoting, obj.isValid ); + if ((s.GetType() & SER_NETWORK) && s.GetVersion() < DMN_TYPE_PROTO_VERSION) { + return; + } if (obj.nVersion == BASIC_BLS_VERSION) { READWRITE(obj.nType); if (obj.nType == MnType::HighPerformance) { diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index b4c12ac655..6b128990d0 100755 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -32,7 +32,7 @@ from test_framework.util import hex_str_to_bytes, assert_equal import dash_hash MIN_VERSION_SUPPORTED = 60001 -MY_VERSION = 70225 # BLS_SCHEME_PROTO_VERSION +MY_VERSION = 70227 # DMN_TYPE_PROTO_VERSION MY_SUBVERSION = b"/python-mininode-tester:0.0.3%s/" MY_RELAY = 1 # from version 70001 onwards, fRelay should be appended to version messages (BIP37) From 0350a48ce291096e2f018355e88df4a814d9c771 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sun, 9 Apr 2023 12:11:22 +0700 Subject: [PATCH 59/63] fix: reviewing TODOes at v19 (#5303) During reviewing TODO were found some TODOes that can be done now. - fix: follow-up dash#3467 - replaced commented code to disabled code - follow-up bitcoin#16394 - uncommented code related to `watchonly` feature - removed out-dated TODO in `rpc/masternode.cpp` (already done) - fix: renamed name of clean up test_unittests: removed TODO and updated name of variable TRAVIS - rewritten todo inside `.travis.yml` - fix: adds a missing description for result of rpc `mnsync` Last commit (`mnsync`) is an only candidate for backport to v19, other changes are non significant. Run functional/unit tests No breaking changes - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone --- .travis.yml | 2 +- ci/dash/test_unittests.sh | 3 +-- src/rpc/masternode.cpp | 1 - src/rpc/misc.cpp | 17 +++++++++++++++-- test/functional/feature_dbcrash.py | 19 +++++++++++-------- test/functional/wallet_createwallet.py | 11 +++++------ 6 files changed, 33 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index a2ed8639d6..242203a557 100644 --- a/.travis.yml +++ b/.travis.yml @@ -176,7 +176,7 @@ before_script: - python3 -c 'import os,sys,fcntl; flags = fcntl.fcntl(sys.stdout, fcntl.F_GETFL); fcntl.fcntl(sys.stdout, fcntl.F_SETFL, flags&~os.O_NONBLOCK);' # Build docker image only for develop branch of the main repo - if [ "$TRAVIS_REPO_SLUG" != "dashpay/dash" -o "$TRAVIS_BRANCH" != "develop" -o "$TRAVIS_PULL_REQUEST" != "false" ]; then export DOCKER_BUILD="false"; echo DOCKER_BUILD=$DOCKER_BUILD; fi - # TODO: Check keys and signed commits + # TODO(ignore if don't use travis): Check keys and signed commits #- if [ "$TRAVIS_REPO_SLUG" = "dashpay/dash" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then while read LINE; do travis_retry gpg --keyserver hkp://subset.pool.sks-keyservers.net --recv-keys $LINE; done < contrib/verify-commits/trusted-keys; fi #- if [ "$TRAVIS_REPO_SLUG" = "dashpay/dash" -a "$TRAVIS_EVENT_TYPE" = "cron" ]; then travis_wait 30 contrib/verify-commits/verify-commits.py; fi after_script: diff --git a/ci/dash/test_unittests.sh b/ci/dash/test_unittests.sh index e7abe0a804..595effffaf 100755 --- a/ci/dash/test_unittests.sh +++ b/ci/dash/test_unittests.sh @@ -16,8 +16,7 @@ if [ "$RUN_UNIT_TESTS" != "true" ]; then exit 0 fi -# TODO this is not Travis agnostic -export BOOST_TEST_RANDOM=1$TRAVIS_BUILD_ID +export BOOST_TEST_RANDOM=${BOOST_TEST_RANDOM:-1} export LD_LIBRARY_PATH=$BASE_BUILD_DIR/depends/$HOST/lib export WINEDEBUG=fixme-all diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 7d4fbb2473..51bd842770 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -82,7 +82,6 @@ static UniValue masternode_connect(const JSONRPCRequest& request) if (!Lookup(strAddress, addr, 0, false)) throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Incorrect masternode address %s", strAddress)); - // TODO: Pass CConnman instance somehow and don't use global variable. NodeContext& node = EnsureNodeContext(request.context); node.connman->OpenMasternodeConnection(CAddress(addr, NODE_NETWORK)); if (!node.connman->IsConnected(CAddress(addr, NODE_NETWORK), CConnman::AllNodes)) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index f9763da996..e00c3e92b5 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -79,8 +79,21 @@ static UniValue mnsync(const JSONRPCRequest& request) { {"mode", RPCArg::Type::STR, RPCArg::Optional::NO, "[status|next|reset]"}, }, - RPCResults{},/*TODO*/ - RPCExamples{""} + { + RPCResult{"for mode = status", + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "AssetID", "The asset ID"}, + {RPCResult::Type::STR, "AssetName", "The asset name"}, + {RPCResult::Type::NUM, "AssetStartTime", "The asset start time"}, + {RPCResult::Type::NUM, "Attempt", "The attempt"}, + {RPCResult::Type::BOOL, "IsBlockchainSynced", "true if the blockchain synced"}, + {RPCResult::Type::BOOL, "IsSynced", "true if synced"}, + }}, + RPCResult{"for mode = next|reset", + RPCResult::Type::STR, "", ""}, + }, + RPCExamples{""}, }.Check(request); std::string strMode = request.params[0].get_str(); diff --git a/test/functional/feature_dbcrash.py b/test/functional/feature_dbcrash.py index 4e99eb5992..01078fe2a1 100755 --- a/test/functional/feature_dbcrash.py +++ b/test/functional/feature_dbcrash.py @@ -232,6 +232,8 @@ class ChainstateWriteCrashTest(BitcoinTestFramework): # Syncing the blocks could cause nodes to crash, so the test begins here. self.sync_node3blocks(block_hashes_to_sync) + starting_tip_height = self.nodes[3].getblockcount() + # Main test loop: # each time through the loop, generate a bunch of transactions, # and then either mine a single new block on the tip, or some-sized reorg. @@ -242,14 +244,15 @@ class ChainstateWriteCrashTest(BitcoinTestFramework): # Pick a random block between current tip, and starting tip current_height = self.nodes[3].getblockcount() # TODO: re-enable this when ReplayBlocks is fixed to support evodb and additional indexes - # random_height = random.randint(starting_tip_height, current_height) - # self.log.debug("At height %d, considering height %d", current_height, random_height) - # if random_height > starting_tip_height: - # # Randomly reorg from this point with some probability (1/4 for - # # tip, 1/5 for tip-1, ...) - # if random.random() < 1.0 / (current_height + 4 - random_height): - # self.log.debug("Invalidating block at height %d", random_height) - # self.nodes[3].invalidateblock(self.nodes[3].getblockhash(random_height)) + skip_this_test_ReplayBlocks = True + random_height = random.randint(starting_tip_height, current_height) + self.log.debug("At height %d, considering height %d", current_height, random_height) + if not skip_this_test_ReplayBlocks and random_height > starting_tip_height: + # Randomly reorg from this point with some probability (1/4 for + # tip, 1/5 for tip-1, ...) + if random.random() < 1.0 / (current_height + 4 - random_height): + self.log.debug("Invalidating block at height %d", random_height) + self.nodes[3].invalidateblock(self.nodes[3].getblockhash(random_height)) # Now generate new blocks until we pass the old tip height self.log.debug("Mining longer tip") diff --git a/test/functional/wallet_createwallet.py b/test/functional/wallet_createwallet.py index 3e90d9cead..cc00c3f9f0 100755 --- a/test/functional/wallet_createwallet.py +++ b/test/functional/wallet_createwallet.py @@ -123,12 +123,11 @@ class CreateWalletTest(BitcoinTestFramework): w7 = node.get_wallet_rpc('w7') assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 10) - # TODO: renable this when avoid reuse flag is added - # self.log.info('Test making a wallet with avoid reuse flag') - # self.nodes[0].createwallet('w8', False, False, '', True) # Use positional arguments to check for bug where avoid_reuse could not be set for wallets without needing them to be encrypted - # w8 = node.get_wallet_rpc('w8') - # assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 10) - # assert_equal(w8.getwalletinfo()["avoid_reuse"], True) + self.log.info('Test making a wallet with avoid reuse flag') + self.nodes[0].createwallet('w8', False, False, '', True) # Use positional arguments to check for bug where avoid_reuse could not be set for wallets without needing them to be encrypted + w8 = node.get_wallet_rpc('w8') + assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 10) + assert_equal(w8.getwalletinfo()["avoid_reuse"], True) self.log.info('Using a passphrase with private keys disabled returns error') assert_raises_rpc_error(-4, 'Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.', self.nodes[0].createwallet, wallet_name='w9', disable_private_keys=True, passphrase='thisisapassphrase') From 798af086b7e6ed46a058952ebd34410ab67ff74a Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sun, 9 Apr 2023 12:10:46 +0700 Subject: [PATCH 60/63] chore: update chainparams for v19.0.0 (#5304) ## Issue being fixed or feature implemented https://github.com/dashpay/dash/issues/5294 ## What was done? Bumped defaultAssumeValid, nMinimumChainWork, chainTxData, checkPointsData ## How Has This Been Tested? Called rpcs `getblockhash N`, `getblock HASH`, `getchaintxstats 17280 HASH` ## Breaking Changes No breaking changes ## Checklist: - [x] I have performed a self-review of my own code - [x] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone --- src/chainparams.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 50242562a1..1f3cbff28f 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -246,10 +246,10 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_V19].nFalloffCoeff = 5; // this corresponds to 10 periods // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000007d31aeabf4a72ce1fbaa"); // 1796500 + consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000082094584a23266cbb5f8"); // 1850400 // By default assume that the signatures in ancestors of this block are valid. - consensus.defaultAssumeValid = uint256S("0x000000000000001d531f36005159f19351bd49ca676398a561e55dcccb84eacd"); // 1796500 + consensus.defaultAssumeValid = uint256S("0x00000000000000261bdbe99c01fcba992e577efa6cc41aae564b8ca9f112b2a3"); // 1850400 /** * The message start string is designed to be unlikely to occur in normal data. @@ -354,15 +354,16 @@ public: {1364585, uint256S("0x00000000000000022f355c52417fca9b73306958f7c0832b3a7bce006ca369ef")}, {1450000, uint256S("0x00000000000000105cfae44a995332d8ec256850ea33a1f7b700474e3dad82bc")}, {1796500, uint256S("0x000000000000001d531f36005159f19351bd49ca676398a561e55dcccb84eacd")}, + {1850400, uint256S("0x00000000000000261bdbe99c01fcba992e577efa6cc41aae564b8ca9f112b2a3")}, } }; - // getchaintxstats 17280 000000000000001d531f36005159f19351bd49ca676398a561e55dcccb84eacd + // getchaintxstats 17280 00000000000000261bdbe99c01fcba992e577efa6cc41aae564b8ca9f112b2a3 chainTxData = ChainTxData{ - 1672362622, // * UNIX timestamp of last known number of transactions (Block 1718597) - 45744554, // * total number of transactions between genesis and that timestamp + 1680866408, // * UNIX timestamp of last known number of transactions (Block 1718597) + 47139357, // * total number of transactions between genesis and that timestamp // (the tx=... number in the ChainStateFlushed debug.log lines) - 0.1522379324797504 // * estimated number of transactions per second after that timestamp + 0.168014362704521, // * estimated number of transactions per second after that timestamp }; } }; @@ -484,10 +485,10 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_V19].nFalloffCoeff = 5; // this corresponds to 10 periods // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000002d68c04d48c0c9c"); // 808000 + consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000002d68cb6c090031f"); // 864000 // By default assume that the signatures in ancestors of this block are valid. - consensus.defaultAssumeValid = uint256S("0x00000104cb60a2b5e00a8a4259582756e5bf0dca201c0993c63f0e54971ea91a"); // 808000 + consensus.defaultAssumeValid = uint256S("0x0000005c35514190ef3c38d322f69412553dc7e1107ed5f92adc2935b90acc51"); // 864000 pchMessageStart[0] = 0xce; pchMessageStart[1] = 0xe2; @@ -567,15 +568,16 @@ public: {470000, uint256S("0x0000009303aeadf8cf3812f5c869691dbd4cb118ad20e9bf553be434bafe6a52")}, {794950, uint256S("0x000001860e4c7248a9c5cc3bc7106041750560dc5cd9b3a2641b49494bcff5f2")}, {808000, uint256S("0x00000104cb60a2b5e00a8a4259582756e5bf0dca201c0993c63f0e54971ea91a")}, + {864000, uint256S("0x0000005c35514190ef3c38d322f69412553dc7e1107ed5f92adc2935b90acc51")}, } }; - // getchaintxstats 17280 00000104cb60a2b5e00a8a4259582756e5bf0dca201c0993c63f0e54971ea91a + // getchaintxstats 17280 0000005c35514190ef3c38d322f69412553dc7e1107ed5f92adc2935b90acc51 chainTxData = ChainTxData{ - 1672374042, // * UNIX timestamp of last known number of transactions (Block 771537) - 5722721, // * total number of transactions between genesis and that timestamp + 1680868209, // * UNIX timestamp of last known number of transactions (Block 771537) + 5847013, // * total number of transactions between genesis and that timestamp // (the tx=... number in the ChainStateFlushed debug.log lines) - 0.003149555626489206 // * estimated number of transactions per second after that timestamp + 0.01994632331955769, // * estimated number of transactions per second after that timestamp }; } }; From dd49bc313b3bf31b85b32be22775a183117c15f9 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Sun, 9 Apr 2023 12:05:39 +0700 Subject: [PATCH 61/63] chore: run `gen-manpages.sh` for 19.0.0 (#5305) ## Issue being fixed or feature implemented https://github.com/dashpay/dash/issues/5294 ## What was done? Called `contrib/devtools/gen-manpages.sh` on top of new assume valid values, see dash#5304 ## How Has This Been Tested? Reviewed only ## Breaking Changes No breaking changes ## Checklist: - [x] I have performed a self-review of my own code - [x] I have assigned this pull request to a milestone --- doc/man/dash-cli.1 | 17 ++++++++++------ doc/man/dash-qt.1 | 47 ++++++++++++++++++++++--------------------- doc/man/dash-tx.1 | 17 ++++++++++------ doc/man/dash-wallet.1 | 17 ++++++++++------ doc/man/dashd.1 | 45 +++++++++++++++++++++-------------------- 5 files changed, 80 insertions(+), 63 deletions(-) diff --git a/doc/man/dash-cli.1 b/doc/man/dash-cli.1 index 281358e051..b80a82e891 100644 --- a/doc/man/dash-cli.1 +++ b/doc/man/dash-cli.1 @@ -1,7 +1,7 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH DASH-CLI "1" "December 2022" "dash-cli v18.2.0" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2. +.TH DASH-CLI "1" "April 2023" "dash-cli v19.0.0" "User Commands" .SH NAME -dash-cli \- manual page for dash-cli v18.2.0 +dash-cli \- manual page for dash-cli v19.0.0 .SH SYNOPSIS .B dash-cli [\fI\,options\/\fR] \fI\, \/\fR[\fI\,params\/\fR] \fI\,Send command to Dash Core\/\fR @@ -15,7 +15,7 @@ dash-cli \- manual page for dash-cli v18.2.0 .B dash-cli [\fI\,options\/\fR] \fI\,help Get help for a command\/\fR .SH DESCRIPTION -Dash Core RPC client version v18.2.0 +Dash Core RPC client version v19.0.0 .SH OPTIONS .HP \-? @@ -142,6 +142,11 @@ devnet\-only) Override the default LLMQ type used for InstantSendDIP0024. (default: llmq_60_75, devnet\-only) .HP +\fB\-llmqplatform=\fR +.IP +Override the default LLMQ type used for Platform. (default: llmq_100_67, +devnet\-only) +.HP \fB\-minimumdifficultyblocks=\fR .IP The number of blocks that can be mined with the minimum difficulty at @@ -156,8 +161,8 @@ minutes, devnet\-only) .IP Use the test chain .SH COPYRIGHT -Copyright (C) 2014-2022 The Dash Core developers -Copyright (C) 2009-2022 The Bitcoin Core developers +Copyright (C) 2014-2023 The Dash Core developers +Copyright (C) 2009-2023 The Bitcoin Core developers Please contribute if you find Dash Core useful. Visit for further information about the software. diff --git a/doc/man/dash-qt.1 b/doc/man/dash-qt.1 index 0a40ae9076..3594aa3a8c 100644 --- a/doc/man/dash-qt.1 +++ b/doc/man/dash-qt.1 @@ -1,12 +1,12 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH DASH-QT "1" "December 2022" "dash-qt v18.2.0" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2. +.TH DASH-QT "1" "April 2023" "dash-qt v19.0.0" "User Commands" .SH NAME -dash-qt \- manual page for dash-qt v18.2.0 +dash-qt \- manual page for dash-qt v19.0.0 .SH SYNOPSIS .B dash-qt [\fI\,command-line options\/\fR] .SH DESCRIPTION -Dash Core version v18.2.0 +Dash Core version v19.0.0 .SH OPTIONS .HP \-? @@ -23,9 +23,9 @@ message) If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: -000000000000001d531f36005159f19351bd49ca676398a561e55dcccb84eacd, +00000000000000261bdbe99c01fcba992e577efa6cc41aae564b8ca9f112b2a3, testnet: -00000104cb60a2b5e00a8a4259582756e5bf0dca201c0993c63f0e54971ea91a) +0000005c35514190ef3c38d322f69412553dc7e1107ed5f92adc2935b90acc51) .HP \fB\-blockfilterindex=\fR .IP @@ -52,9 +52,8 @@ Specify directory to hold blocks subdirectory for *.dat files (default: .IP Whether to reject transactions from network peers. Automatic broadcast and rebroadcast of any transactions from inbound peers is -disabled, unless '\-whitelistforcerelay' is '1', in which case -whitelisted peers' transactions will be relayed. RPC transactions -are not affected. (default: 0) +disabled, unless the peer has the 'forcerelay' permission. RPC +transactions are not affected. (default: 0) .HP \fB\-conf=\fR .IP @@ -109,7 +108,7 @@ Do not keep transactions in the mempool longer than hours (default: .HP \fB\-par=\fR .IP -Set the number of script verification threads (\fB\-4\fR to 15, 0 = auto, <0 = +Set the number of script verification threads (\fB\-24\fR to 15, 0 = auto, <0 = leave that many cores free, default: 0) .HP \fB\-persistmempool\fR @@ -468,18 +467,15 @@ start from wallet creation time, 2 = start from genesis block) .IP Spend unconfirmed change when sending transactions (default: 1) .HP -\fB\-upgradewallet\fR -.IP -Upgrade wallet to latest format on startup -.HP \fB\-wallet=\fR .IP -Specify wallet database path. Can be specified multiple times to load -multiple wallets. Path is interpreted relative to if -it is not absolute, and will be created if it does not exist (as -a directory containing a wallet.dat file and log files). For -backwards compatibility this will also accept names of existing -data files in .) +Specify wallet path to load at startup. Can be used multiple times to +load multiple wallets. Path is to a directory containing wallet +data and log files. If the path is not absolute, it is +interpreted relative to . This only loads existing +wallets and does not create new ones. For backwards compatibility +this also accepts names of existing top\-level data files in +. .HP \fB\-walletbackupsdir=\fR .IP @@ -868,6 +864,11 @@ devnet\-only) Override the default LLMQ type used for InstantSendDIP0024. (default: llmq_60_75, devnet\-only) .HP +\fB\-llmqplatform=\fR +.IP +Override the default LLMQ type used for Platform. (default: llmq_100_67, +devnet\-only) +.HP \fB\-minimumdifficultyblocks=\fR .IP The number of blocks that can be mined with the minimum difficulty at @@ -1028,7 +1029,7 @@ Set the font weight for bold texts. Possible range 0 to 8 (default: 4) .HP \fB\-font\-weight\-normal\fR .IP -Set the font weight for normal texts. Possible range 0 to 8 (default: 1) +Set the font weight for normal texts. Possible range 0 to 8 (default: 2) .HP \fB\-lang=\fR .IP @@ -1050,8 +1051,8 @@ Show splash screen on startup (default: 1) .IP Sets a window title which is appended to "Dash Core \- " .SH COPYRIGHT -Copyright (C) 2014-2022 The Dash Core developers -Copyright (C) 2009-2022 The Bitcoin Core developers +Copyright (C) 2014-2023 The Dash Core developers +Copyright (C) 2009-2023 The Bitcoin Core developers Please contribute if you find Dash Core useful. Visit for further information about the software. diff --git a/doc/man/dash-tx.1 b/doc/man/dash-tx.1 index ea733fa6d5..a0691112d8 100644 --- a/doc/man/dash-tx.1 +++ b/doc/man/dash-tx.1 @@ -1,7 +1,7 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH DASH-TX "1" "December 2022" "dash-tx v18.2.0" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2. +.TH DASH-TX "1" "April 2023" "dash-tx v19.0.0" "User Commands" .SH NAME -dash-tx \- manual page for dash-tx v18.2.0 +dash-tx \- manual page for dash-tx v19.0.0 .SH SYNOPSIS .B dash-tx [\fI\,options\/\fR] \fI\, \/\fR[\fI\,commands\/\fR] \fI\,Update hex-encoded dash transaction\/\fR @@ -9,7 +9,7 @@ dash-tx \- manual page for dash-tx v18.2.0 .B dash-tx [\fI\,options\/\fR] \fI\,-create \/\fR[\fI\,commands\/\fR] \fI\,Create hex-encoded dash transaction\/\fR .SH DESCRIPTION -Dash Core dash\-tx utility version v18.2.0 +Dash Core dash\-tx utility version v19.0.0 .SH OPTIONS .HP \-? @@ -65,6 +65,11 @@ devnet\-only) Override the default LLMQ type used for InstantSendDIP0024. (default: llmq_60_75, devnet\-only) .HP +\fB\-llmqplatform=\fR +.IP +Override the default LLMQ type used for Platform. (default: llmq_100_67, +devnet\-only) +.HP \fB\-minimumdifficultyblocks=\fR .IP The number of blocks that can be mined with the minimum difficulty at @@ -142,8 +147,8 @@ set=NAME:JSON\-STRING .IP Set register NAME to given JSON\-STRING .SH COPYRIGHT -Copyright (C) 2014-2022 The Dash Core developers -Copyright (C) 2009-2022 The Bitcoin Core developers +Copyright (C) 2014-2023 The Dash Core developers +Copyright (C) 2009-2023 The Bitcoin Core developers Please contribute if you find Dash Core useful. Visit for further information about the software. diff --git a/doc/man/dash-wallet.1 b/doc/man/dash-wallet.1 index a1203de0e0..b3ff83e20b 100644 --- a/doc/man/dash-wallet.1 +++ b/doc/man/dash-wallet.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH DASH-WALLET "1" "December 2022" "dash-wallet v18.2.0" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2. +.TH DASH-WALLET "1" "April 2023" "dash-wallet v19.0.0" "User Commands" .SH NAME -dash-wallet \- manual page for dash-wallet v18.2.0 +dash-wallet \- manual page for dash-wallet v19.0.0 .SH DESCRIPTION -Dash Core dash\-wallet version v18.2.0 +Dash Core dash\-wallet version v19.0.0 .PP dash\-wallet is an offline tool for creating and interacting with Dash Core wallet files. By default dash\-wallet will act on wallets in the default mainnet wallet directory in the datadir. @@ -73,6 +73,11 @@ devnet\-only) Override the default LLMQ type used for InstantSendDIP0024. (default: llmq_60_75, devnet\-only) .HP +\fB\-llmqplatform=\fR +.IP +Override the default LLMQ type used for Platform. (default: llmq_100_67, +devnet\-only) +.HP \fB\-minimumdifficultyblocks=\fR .IP The number of blocks that can be mined with the minimum difficulty at @@ -101,8 +106,8 @@ salvage .IP Attempt to recover private keys from a corrupt wallet .SH COPYRIGHT -Copyright (C) 2014-2022 The Dash Core developers -Copyright (C) 2009-2022 The Bitcoin Core developers +Copyright (C) 2014-2023 The Dash Core developers +Copyright (C) 2009-2023 The Bitcoin Core developers Please contribute if you find Dash Core useful. Visit for further information about the software. diff --git a/doc/man/dashd.1 b/doc/man/dashd.1 index 73a8b97180..7c9d6f412a 100644 --- a/doc/man/dashd.1 +++ b/doc/man/dashd.1 @@ -1,12 +1,12 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH DASHD "1" "December 2022" "dashd v18.2.0" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2. +.TH DASHD "1" "April 2023" "dashd v19.0.0" "User Commands" .SH NAME -dashd \- manual page for dashd v18.2.0 +dashd \- manual page for dashd v19.0.0 .SH SYNOPSIS .B dashd [\fI\,options\/\fR] \fI\,Start Dash Core Daemon\/\fR .SH DESCRIPTION -Dash Core Daemon version v18.2.0 +Dash Core Daemon version v19.0.0 .SH OPTIONS .HP \-? @@ -23,9 +23,9 @@ message) If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: -000000000000001d531f36005159f19351bd49ca676398a561e55dcccb84eacd, +00000000000000261bdbe99c01fcba992e577efa6cc41aae564b8ca9f112b2a3, testnet: -00000104cb60a2b5e00a8a4259582756e5bf0dca201c0993c63f0e54971ea91a) +0000005c35514190ef3c38d322f69412553dc7e1107ed5f92adc2935b90acc51) .HP \fB\-blockfilterindex=\fR .IP @@ -52,9 +52,8 @@ Specify directory to hold blocks subdirectory for *.dat files (default: .IP Whether to reject transactions from network peers. Automatic broadcast and rebroadcast of any transactions from inbound peers is -disabled, unless '\-whitelistforcerelay' is '1', in which case -whitelisted peers' transactions will be relayed. RPC transactions -are not affected. (default: 0) +disabled, unless the peer has the 'forcerelay' permission. RPC +transactions are not affected. (default: 0) .HP \fB\-conf=\fR .IP @@ -109,7 +108,7 @@ Do not keep transactions in the mempool longer than hours (default: .HP \fB\-par=\fR .IP -Set the number of script verification threads (\fB\-4\fR to 15, 0 = auto, <0 = +Set the number of script verification threads (\fB\-24\fR to 15, 0 = auto, <0 = leave that many cores free, default: 0) .HP \fB\-persistmempool\fR @@ -468,18 +467,15 @@ start from wallet creation time, 2 = start from genesis block) .IP Spend unconfirmed change when sending transactions (default: 1) .HP -\fB\-upgradewallet\fR -.IP -Upgrade wallet to latest format on startup -.HP \fB\-wallet=\fR .IP -Specify wallet database path. Can be specified multiple times to load -multiple wallets. Path is interpreted relative to if -it is not absolute, and will be created if it does not exist (as -a directory containing a wallet.dat file and log files). For -backwards compatibility this will also accept names of existing -data files in .) +Specify wallet path to load at startup. Can be used multiple times to +load multiple wallets. Path is to a directory containing wallet +data and log files. If the path is not absolute, it is +interpreted relative to . This only loads existing +wallets and does not create new ones. For backwards compatibility +this also accepts names of existing top\-level data files in +. .HP \fB\-walletbackupsdir=\fR .IP @@ -868,6 +864,11 @@ devnet\-only) Override the default LLMQ type used for InstantSendDIP0024. (default: llmq_60_75, devnet\-only) .HP +\fB\-llmqplatform=\fR +.IP +Override the default LLMQ type used for Platform. (default: llmq_100_67, +devnet\-only) +.HP \fB\-minimumdifficultyblocks=\fR .IP The number of blocks that can be mined with the minimum difficulty at @@ -1001,8 +1002,8 @@ subject to empty whitelists. .IP Accept command line and JSON\-RPC commands .SH COPYRIGHT -Copyright (C) 2014-2022 The Dash Core developers -Copyright (C) 2009-2022 The Bitcoin Core developers +Copyright (C) 2014-2023 The Dash Core developers +Copyright (C) 2009-2023 The Bitcoin Core developers Please contribute if you find Dash Core useful. Visit for further information about the software. From 262ce6c4554372d4d53be99c38bd91306a452fd8 Mon Sep 17 00:00:00 2001 From: pasta Date: Sun, 9 Apr 2023 21:49:23 -0500 Subject: [PATCH 62/63] chore: bump version to final --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index f6183f9d84..3dd3669e8a 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,8 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 19) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 10) -define(_CLIENT_VERSION_IS_RELEASE, false) +define(_CLIENT_VERSION_RC, 0) +define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2023) define(_COPYRIGHT_HOLDERS,[The %s developers]) define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[Dash Core]]) From 4266edf784887805ce84bd4929b70d543a648c0b Mon Sep 17 00:00:00 2001 From: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> Date: Mon, 10 Apr 2023 12:30:30 -0500 Subject: [PATCH 63/63] doc: update the content of release notes for v19.0.0 and archive old release notes Co-authored-by: thephez --- doc/release-notes-15427.md | 8 - doc/release-notes-15454.md | 6 - doc/release-notes-4892.md | 34 --- doc/release-notes-5021.md | 71 ------ doc/release-notes-5039.md | 18 -- doc/release-notes-5112.md | 4 - doc/release-notes-5125.md | 4 - doc/release-notes-5158.md | 4 - doc/release-notes-5164.md | 5 - doc/release-notes-5206.md | 5 - doc/release-notes-5225.md | 10 - doc/release-notes-5273.md | 5 - doc/release-notes.md | 220 ++++++++++++++---- .../dash/release-notes-18.2.2.md | 171 ++++++++++++++ doc/release-notes/release-notes-20186.md | 16 -- 15 files changed, 340 insertions(+), 241 deletions(-) delete mode 100644 doc/release-notes-15427.md delete mode 100644 doc/release-notes-15454.md delete mode 100644 doc/release-notes-4892.md delete mode 100644 doc/release-notes-5021.md delete mode 100644 doc/release-notes-5039.md delete mode 100644 doc/release-notes-5112.md delete mode 100644 doc/release-notes-5125.md delete mode 100644 doc/release-notes-5158.md delete mode 100644 doc/release-notes-5164.md delete mode 100644 doc/release-notes-5206.md delete mode 100644 doc/release-notes-5225.md delete mode 100644 doc/release-notes-5273.md create mode 100644 doc/release-notes/dash/release-notes-18.2.2.md delete mode 100644 doc/release-notes/release-notes-20186.md diff --git a/doc/release-notes-15427.md b/doc/release-notes-15427.md deleted file mode 100644 index 8488ecf545..0000000000 --- a/doc/release-notes-15427.md +++ /dev/null @@ -1,8 +0,0 @@ -Updated RPCs ------------- - -The `utxoupdatepsbt` RPC method has been updated to take a `descriptors` -argument. When provided, input and output scripts and keys will be filled in -when known. - -See the RPC help text for full details. diff --git a/doc/release-notes-15454.md b/doc/release-notes-15454.md deleted file mode 100644 index 9cb0368084..0000000000 --- a/doc/release-notes-15454.md +++ /dev/null @@ -1,6 +0,0 @@ -Wallet ------- - -Dash Core will no longer create an unnamed `""` wallet by default when no wallet is specified on the command line or in the configuration files. -For backwards compatibility, if an unnamed `""` wallet already exists and would have been loaded previously, then it will still be loaded. -Users without an unnamed `""` wallet and without any other wallets to be loaded on startup will be prompted to either choose a wallet to load, or to create a new wallet. diff --git a/doc/release-notes-4892.md b/doc/release-notes-4892.md deleted file mode 100644 index 00cb35cf06..0000000000 --- a/doc/release-notes-4892.md +++ /dev/null @@ -1,34 +0,0 @@ -P2P and network changes ------------------------ - -#### Removal of reject network messages from Dash Core (BIP61) - -The command line option to enable BIP61 (`-enablebip61`) has been removed. - -This feature has been disabled by default since Dash Core version 0.19.0. -Nodes on the network can not generally be trusted to send valid ("reject") -messages, so this should only ever be used when connected to a trusted node. -Please use the recommended alternatives if you rely on this deprecated feature: - -* Testing or debugging of implementations of the Dash P2P network protocol - should be done by inspecting the log messages that are produced by a recent - version of Dash Core. Dash Core logs debug messages - (`-debug=`) to a stream (`-printtoconsole`) or to a file - (`-debuglogfile=`). - -* Testing the validity of a block can be achieved by specific RPCs: - - `submitblock` - - `getblocktemplate` with `'mode'` set to `'proposal'` for blocks with - potentially invalid POW - -* Testing the validity of a transaction can be achieved by specific RPCs: - - `sendrawtransaction` - - `testmempoolaccept` - -* Wallets should not use the absence of "reject" messages to indicate a - transaction has propagated the network, nor should wallets use "reject" - messages to set transaction fees. Wallets should rather use fee estimation - to determine transaction fees and set replace-by-fee if desired. Thus, they - could wait until the transaction has confirmed (taking into account the fee - target they set (compare the RPC `estimatesmartfee`)) or listen for the - transaction announcement by other network peers to check for propagation. diff --git a/doc/release-notes-5021.md b/doc/release-notes-5021.md deleted file mode 100644 index 6a62d49ede..0000000000 --- a/doc/release-notes-5021.md +++ /dev/null @@ -1,71 +0,0 @@ -Added RPCs --------- - -- Once the v19 hard fork is activated, `protx register`, `protx register_fund`, and `protx register_prepare` RPCs will decode BLS operator public keys using the new basic BLS scheme. In order to support BLS public keys encoded in the legacy BLS scheme, `protx register_legacy`, `protx register_fund_legacy`, and `protx register_prepare_legacy` were added. - -Other changes --------- - -`qfcommit` --------- - -Once the v19 hard fork is activated, `quorumPublicKey` will be serialised using the basic BLS scheme. -To support syncing of older blocks containing the transactions using the legacy BLS scheme, the `version` field indicates which scheme to use for serialisation of `quorumPublicKey`. - -| Version | Version Description | Includes `quorumIndex` field | -|---------|--------------------------------------------------------|------------------------------| -| 1 | Non-rotated qfcommit serialised using legacy BLS scheme | No | -| 2 | Rotated qfcommit serialised using legacy BLS scheme | Yes | -| 3 | Non-rotated qfcommit serialised using basic BLS scheme | No | -| 4 | Rotated qfcommit serialised using basic BLS scheme | Yes | - -`MNLISTDIFF` P2P message --------- - -Starting with protocol version 70225, the following field is added to the `MNLISTDIFF` message between `cbTx` and `deletedQuorumsCount`. - -| Field | Type | Size | Description | -|---------------------| ---- | ---- |-----------------------------------| -| version | uint16_t | 2 | Version of the `MNLISTDIFF` reply | - -The `version` field indicates which BLS scheme is used to serialise the `pubKeyOperator` field for all SML entries of `mnList`. - -| Version | Version Description | -|---------|-----------------------------------------------------------| -| 1 | Serialisation of `pubKeyOperator` using legacy BLS scheme | -| 2 | Serialisation of `pubKeyOperator` using basic BLS scheme | - -`ProTx` txs family --------- - -`proregtx` and `proupregtx` will support a new `version` value: - -| Version | Version Description | -|---------|-----------------------------------------------------------| -| 1 | Serialisation of `pubKeyOperator` using legacy BLS scheme | -| 2 | Serialisation of `pubKeyOperator` using basic BLS scheme | - -`proupservtx` and `prouprevtx` will support a new `version` value: - -| Version | Version Description | -|---------|------------------------------------------------| -| 1 | Serialisation of `sig` using legacy BLS scheme | -| 2 | Serialisation of `sig` using basic BLS scheme | - -`MNHFTx` --------- - -`MNHFTx` will support a new `version` value: - -| Version | Version Description | -|---------|------------------------------------------------| -| 1 | Serialisation of `sig` using legacy BLS scheme | -| 2 | Serialisation of `sig` using basic BLS scheme | - -BLS enforced scheme --------- -Once the v19 hard fork is activated, all remaining messages containing BLS public keys or signatures will serialise them using the new basic BLS scheme. -The motivation behind this change is the need to be aligned with IETF standards. - -List of affected messages: -`dsq`, `dstx`, `mnauth`, `govobj`, `govobjvote`, `qrinfo`, `qsigshare`, `qsigrec`, `isdlock`, `clsig`, and all DKG messages (`qfcommit`, `qcontrib`, `qcomplaint`, `qjustify`, `qpcommit`). diff --git a/doc/release-notes-5039.md b/doc/release-notes-5039.md deleted file mode 100644 index 78b137b510..0000000000 --- a/doc/release-notes-5039.md +++ /dev/null @@ -1,18 +0,0 @@ -Added RPCs --------- - -The following RPCs were added: `protx register_hpmn`, `protx register_fund_hpmn`, `protx register_prepare_hpmn` and `protx update_service_hpmn`. -These HPMN RPCs correspond to the standard masternode RPCs but have the following additional mandatory arguments: `platformNodeID`, `platformP2PPort` and `platformHTTPPort`. -- `platformNodeID`: Platform P2P node ID, derived from P2P public key. -- `platformP2PPort`: TCP port of Dash Platform peer-to-peer communication between nodes (network byte order). -- `platformHTTPPort`: TCP port of Platform HTTP/API interface (network byte order). -Notes: -- `platformNodeID` must be unique across the network. -- `platformP2PPort`, `platformHTTPPort` and the Core port must be distinct. - - -Updated RPCs --------- - -The RPC's `gobject getcurrentvotes` reply is enriched by adding the vote weight at the end of each line. Possible values are 1 or 4. Example: -`"7cb20c883c6093b8489f795b3ec0aad0d9c2c2821610ae9ed938baaf42fec66d": "277e6345359071410ab691c21a3a16f8f46c9229c2f8ec8f028c9a95c0f1c0e7-1:1670019339:yes:funding:4"` \ No newline at end of file diff --git a/doc/release-notes-5112.md b/doc/release-notes-5112.md deleted file mode 100644 index 5d574daeba..0000000000 --- a/doc/release-notes-5112.md +++ /dev/null @@ -1,4 +0,0 @@ -Updated settings ----------------- - -- Passing an invalid `-rpcauth` argument now cause dashd to fail to start. diff --git a/doc/release-notes-5125.md b/doc/release-notes-5125.md deleted file mode 100644 index 895ae1ef65..0000000000 --- a/doc/release-notes-5125.md +++ /dev/null @@ -1,4 +0,0 @@ -Updated RPCs --------- - -- `masternodelist` New mode `recent` was added in order to hide banned masternodes for more than one `SuperblockCycle`. If the mode `recent` is used, then the reply mode is JSON (can be additionally filtered) diff --git a/doc/release-notes-5158.md b/doc/release-notes-5158.md deleted file mode 100644 index 22367d93ce..0000000000 --- a/doc/release-notes-5158.md +++ /dev/null @@ -1,4 +0,0 @@ -Updated RPCs --------- - -- `quorum info`: The new `previousConsecutiveDKGFailures` field will be returned for rotated LLMQs. This field will hold the number of previous consecutive DKG failures for the corresponding quorumIndex before the currently active one. Note: If no previous commitments were found then 0 will be returned for `previousConsecutiveDKGFailures`. diff --git a/doc/release-notes-5164.md b/doc/release-notes-5164.md deleted file mode 100644 index 0be8d178a4..0000000000 --- a/doc/release-notes-5164.md +++ /dev/null @@ -1,5 +0,0 @@ -Updated RPCs --------- - -- `bls generate` and `bls fromsecret`: The new `scheme` field will be returned indicating which scheme was used to serialise the public key. Valid returned values are `legacy` and`basic`. -- `bls generate` and `bls fromsecret`: Both RPCs accept an incoming optional boolean argument `legacy` that enforces the use of legacy BLS scheme for the serialisation of the reply even if v19 is active. diff --git a/doc/release-notes-5206.md b/doc/release-notes-5206.md deleted file mode 100644 index e2bdf73b79..0000000000 --- a/doc/release-notes-5206.md +++ /dev/null @@ -1,5 +0,0 @@ -Updated RPCs --------- - -- `masternode` mode `status` now returns the type of the masternode. -- `masternode` mode `count` now returns a detailed summary of total and enabled masternodes per type. diff --git a/doc/release-notes-5225.md b/doc/release-notes-5225.md deleted file mode 100644 index e6cdc29679..0000000000 --- a/doc/release-notes-5225.md +++ /dev/null @@ -1,10 +0,0 @@ -Testnet Breaking Changes ------------------------- - -A new testnet only LLMQ has been added. This LLMQ is of the type LLMQ_25_67; this LLMQ is only active on testnet. -This LLMQ will not remove the LLMQ_100_67 from testnet; however that quorum (likely) will not form and will perform no role. -See the [diff](https://github.com/dashpay/dash/pull/5225/files#diff-e70a38a3e8c2a63ca0494627301a5c7042141ad301193f78338d97cb1b300ff9R451-R469) for specific parameters of the LLMQ. - -This LLMQ will become active at the height of 847000. **This will be a breaking change and a hard fork for testnet** -This LLMQ is not activated with the v19 hardfork; as such testnet will experience two hardforks. One at height 847000, -and the other to be determined by the BIP9 hard fork process. diff --git a/doc/release-notes-5273.md b/doc/release-notes-5273.md deleted file mode 100644 index 16bd0c88dc..0000000000 --- a/doc/release-notes-5273.md +++ /dev/null @@ -1,5 +0,0 @@ -Added RPCs --------- - -- `cleardiscouraged` clears all the already discouraged peers. - diff --git a/doc/release-notes.md b/doc/release-notes.md index 51c7891cb6..18d050f270 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -1,26 +1,22 @@ -Dash Core version v18.2.2 -========================= +# Dash Core version v19.0.0 Release is now available from: -This is a new hotfix version release. +This is a new major version release, bringing new features, various bugfixes +and other improvements. -This release is optional for all nodes; however, v18.2.2 or higher is required -to be able to use testnet right until v19 hard fork activation. Earlier -versions will not be able to sync past block 847000 on testnet. +This release is mandatory for all nodes. Please report bugs using the issue tracker at GitHub: -Upgrading and downgrading -========================= +# Upgrading and downgrading -How to Upgrade --------------- +## 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 @@ -36,82 +32,203 @@ from a few minutes to thirty minutes to finish. After the migration, a downgrade to an older version is only possible with a reindex (or reindex-chainstate). -Downgrade warning ------------------ +## Downgrade warning -### Downgrade to a version < v18.2.2 +### Downgrade to a version < v19.0.0 +Downgrading to a version older than v19.0.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. -Downgrading to a version older than v18.2.2 is supported. +# Notable changes -### Downgrade to a version < v18.0.1 +## High-Performance Masternodes -Downgrading to a version older than v18.0.1 is not supported due to changes in -the indexes database folder. If you need to use an older version, you must -either reindex or re-sync the whole chain. +In preparation for the release of Dash Platform to mainnet, a new masternode type has been added. High-performance masternodes will be responsible for hosting Dash Platform services (once they are on mainnet) in addition to the existing responsibilities like ChainLocks and InstantSend. -Notable changes -=============== +Activation of the DashCore v19.0 hard fork will enable registration of the new 4000 DASH collateral masternodes. Until Dash Platform is released to mainnet, high-performance masternodes will provide the same services as regular masternodes with one small exception. Regular masternodes will no longer participate in the Platform-specific LLMQ after the hard fork since they will not be responsible for hosting Dash Platform. -Testnet Breaking Changes ------------------------- +Note: In DashCore v19.0 the relative rewards and voting power are equivalent between regular and high-performance masternodes. Masternodes effectively receive one payout and one governance vote per 1000 DASH collateral. So, there is no difference in reward amount for running four regular masternodes or one high-performance masternode. In v19.0, high-performance masternodes simply receive payments in four consecutive blocks when they are selected for payout. Some frequently asked questions may be found at https://www.dash.org/hpmn-faq/. -A new testnet only LLMQ has been added. This LLMQ is of the type LLMQ_25_67; this LLMQ is only active on testnet. -This LLMQ will not remove the LLMQ_100_67 from testnet; however that quorum (likely) will not form and will perform no role. -See the [diff](https://github.com/dashpay/dash/pull/5225/files#diff-e70a38a3e8c2a63ca0494627301a5c7042141ad301193f78338d97cb1b300ff9R451-R469) for specific parameters of the LLMQ. +## BLS Scheme Upgrade -This LLMQ will become active at the height of 847000. **This will be a breaking change and a hard fork for testnet** -This LLMQ is not activated with the v19 hardfork; as such testnet will experience two hardforks. One at height 847000, -and the other to be determined by the BIP9 hard fork process. +Once the v19 hard fork is activated, all remaining messages containing BLS public keys or signatures will serialise them using the new basic BLS scheme. +The motivation behind this change is the need to be aligned with IETF standards. -Remote Procedure Call (RPC) Changes ------------------------------------ +List of affected messages: +`dsq`, `dstx`, `mnauth`, `govobj`, `govobjvote`, `qrinfo`, `qsigshare`, `qsigrec`, `isdlock`, `clsig`, and all DKG messages (`qfcommit`, `qcontrib`, `qcomplaint`, `qjustify`, `qpcommit`). + +### `qfcommit` + +Once the v19 hard fork is activated, `quorumPublicKey` will be serialised using the basic BLS scheme. +To support syncing of older blocks containing the transactions using the legacy BLS scheme, the `version` field indicates which scheme to use for serialisation of `quorumPublicKey`. + +| Version | Version Description | Includes `quorumIndex` field | +|---------|--------------------------------------------------------|------------------------------| +| 1 | Non-rotated qfcommit serialised using legacy BLS scheme | No | +| 2 | Rotated qfcommit serialised using legacy BLS scheme | Yes | +| 3 | Non-rotated qfcommit serialised using basic BLS scheme | No | +| 4 | Rotated qfcommit serialised using basic BLS scheme | Yes | + +### `MNLISTDIFF` P2P message + +Starting with protocol version 70225, the following field is added to the `MNLISTDIFF` message between `cbTx` and `deletedQuorumsCount`. + +| Field | Type | Size | Description | +|---------------------| ---- | ---- |-----------------------------------| +| version | uint16_t | 2 | Version of the `MNLISTDIFF` reply | + +The `version` field indicates which BLS scheme is used to serialise the `pubKeyOperator` field for all SML entries of `mnList`. + +| Version | Version Description | +|---------|-----------------------------------------------------------| +| 1 | Serialisation of `pubKeyOperator` using legacy BLS scheme | +| 2 | Serialisation of `pubKeyOperator` using basic BLS scheme | + +### `ProTx` txs family + +`proregtx` and `proupregtx` will support a new `version` value: + +| Version | Version Description | +|---------|-----------------------------------------------------------| +| 1 | Serialisation of `pubKeyOperator` using legacy BLS scheme | +| 2 | Serialisation of `pubKeyOperator` using basic BLS scheme | + +`proupservtx` and `prouprevtx` will support a new `version` value: + +| Version | Version Description | +|---------|------------------------------------------------| +| 1 | Serialisation of `sig` using legacy BLS scheme | +| 2 | Serialisation of `sig` using basic BLS scheme | + +### `MNHFTx` + +`MNHFTx` will support a new `version` value: + +| Version | Version Description | +|---------|------------------------------------------------| +| 1 | Serialisation of `sig` using legacy BLS scheme | +| 2 | Serialisation of `sig` using basic BLS scheme | + +## Wallet + +## Automatic wallet creation removed + +Dash Core will no longer automatically create new wallets on startup. It will +load existing wallets specified by -wallet options on the command line or in +dash.conf or settings.json files. And by default it will also load a +top-level unnamed ("") wallet. However, if specified wallets don't exist, +Dash Core will now just log warnings instead of creating new wallets with +new keys and addresses like previous releases did. + +New wallets can be created through the GUI (which has a more prominent create +wallet option), through the dash-wallet create command or the createwallet RPC. + +## P2P and Network Changes + +## Removal of reject network messages from Dash Core (BIP61) + +The command line option to enable BIP61 (-enablebip61) has been removed. + +Nodes on the network can not generally be trusted to send valid ("reject") +messages, so this should only ever be used when connected to a trusted node. +Please use the recommended alternatives if you rely on this deprecated feature: + +- Testing or debugging of implementations of the Dash P2P network protocol +should be done by inspecting the log messages that are produced by a recent +version of Dash Core. Dash Core logs debug messages +(-debug=) to a stream (-printtoconsole) or to a file +(-debuglogfile=). + +- Testing the validity of a block can be achieved by specific RPCs: + - submitblock + - getblocktemplate with 'mode' set to 'proposal' for blocks with + - potentially invalid POW + - Testing the validity of a transaction can be achieved by specific RPCs: + - sendrawtransaction + - testmempoolaccept + +## CoinJoin update + +A minor update in several CoinJoin-related network messages improves support +for mixing from SPV clients. These changes make it easier for SPV clients to +participate in the CoinJoin process by using masternode information they can +readily obtain and verify via [DIP-0004](https://github.com/dashpay/dips/blob/master/dip-0004.md). + +## Remote Procedure Call (RPC) Changes ### The new RPCs are: -None +- In order to support BLS public keys encoded in the legacy BLS scheme, `protx register_legacy`, `protx register_fund_legacy`, and `protx register_prepare_legacy` were added. +- `cleardiscouraged` clears all the already discouraged peers. +- The following RPCs were added: `protx register_hpmn`, `protx register_fund_hpmn`, `protx register_prepare_hpmn` and `protx update_service_hpmn`. + These HPMN RPCs correspond to the standard masternode RPCs but have the following additional mandatory arguments: `platformNodeID`, `platformP2PPort` and `platformHTTPPort`. +- `upgradewallet` ### The removed RPCs are: + None ### Changes in existing RPCs introduced through bitcoin backports: -None + +- The `utxoupdatepsbt` RPC method has been updated to take a descriptors +argument. When provided, input and output scripts and keys will be filled in +when known. See the RPC help text for full details. + ### Dash-specific changes in existing RPCs: -None + +- `masternodelist`: New mode `recent` was added in order to hide banned masternodes for more than one `SuperblockCycle`. If the mode `recent` is used, then the reply mode is JSON (can be additionally filtered) +- `quorum info`: The new `previousConsecutiveDKGFailures` field will be returned for rotated LLMQs. This field will hold the number of previous consecutive DKG failures for the corresponding quorumIndex before the currently active one. Note: If no previous commitments were found then 0 will be returned for `previousConsecutiveDKGFailures`. +- `bls generate` and `bls fromsecret`: The new `scheme` field will be returned indicating which scheme was used to serialise the public key. Valid returned values are `legacy` and`basic`. +- `bls generate` and `bls fromsecret`: Both RPCs accept an incoming optional boolean argument `legacy` that enforces the use of legacy BLS scheme for the serialisation of the reply even if v19 is active. +- `masternode status`: now returns the type of the masternode. +- `masternode count`: now returns a detailed summary of total and enabled masternodes per type. +- `gobject getcurrentvotes`: reply is enriched by adding the vote weight at the end of each line. Possible values are 1 or 4. Example: "7cb20c883c6093b8489f795b3ec0aad0d9c2c2821610ae9ed938baaf42fec66d": "277e6345359071410ab691c21a3a16f8f46c9229c2f8ec8f028c9a95c0f1c0e7-1:1670019339:yes:funding:4" +- Once the v19 hard fork is activated, `protx register`, `protx register_fund`, and `protx register_prepare` RPCs will decode BLS operator public keys using the new basic BLS scheme. Please check `help ` for more detailed information on specific RPCs. -Command-line options --------------------- -None +## Command-line options + +A number of command-line option changes were made related to testing and +removal of BIP61 support. + +New cmd-line options: +- `llmqplatform` (devnet only) +- `unsafesqlitesync` + +Removed cmd-line options: +- `enablebip61` +- `upgradewallet` + +Changes in existing cmd-line options: +- `llmqinstantsend` and `llmqinstantsenddip0024` can be used in regtest now +- Passing an invalid `-rpcauth` argument now cause dashd to fail to start. Please check `Help -> Command-line options` in Qt wallet or `dashd --help` for more information. -Backports from Bitcoin Core ---------------------------- -None +## Backports from Bitcoin Core -Other changes -------------- -#5247 is backported to improve debugging experience. +This release introduces many updates from Bitcoin v0.18-v0.21 as well as numerous updates from Bitcoin v22 and more recent versions. Bitcoin changes that do not align with Dash’s product needs, such as SegWit and RBF, are excluded from our backporting. For additional detail on what’s included in Bitcoin, please refer to their release notes. -v18.2.2 Change log -================== +# v19.0.0 Change log -See detailed [set of changes](https://github.com/dashpay/dash/compare/v18.2.1...dashpay:v18.2.2). +See detailed [set of changes](https://github.com/dashpay/dash/compare/v18.2.2...dashpay:v19.0.0). -Credits -======= +# Credits Thanks to everyone who directly contributed to this release: -- Odysseas Gabrielides +- Kittywhiskers Van Gogh (kittywhiskers) +- Konstantin Akimov (knst) +- Odysseas Gabrielides (ogabrielides) +- Oleg Girko (OlegGirko) +- PastaPastaPasta +- thephez - UdjinM6 +- Vijay Das Manikpuri (vijaydasmp) As well as everyone that submitted issues, reviewed pull requests, helped debug the release candidates, and write DIPs that were implemented in this release. -Older releases -============== +# Older releases Dash was previously known as Darkcoin. @@ -133,7 +250,8 @@ Dash Core tree 0.12.1.x was a fork of Bitcoin Core tree 0.12. These release are considered obsolete. Old release notes can be found here: -- [v18.2.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.2.2.md) released Jan/17/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 diff --git a/doc/release-notes/dash/release-notes-18.2.2.md b/doc/release-notes/dash/release-notes-18.2.2.md new file mode 100644 index 0000000000..51c7891cb6 --- /dev/null +++ b/doc/release-notes/dash/release-notes-18.2.2.md @@ -0,0 +1,171 @@ +Dash Core version v18.2.2 +========================= + +Release is now available from: + + + +This is a new hotfix version release. + +This release is optional for all nodes; however, v18.2.2 or higher is required +to be able to use testnet right until v19 hard fork activation. Earlier +versions will not be able to sync past block 847000 on testnet. + +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). If you upgrade after DIP0003 activation and you were +using version < 0.13 you will have to reindex (start with -reindex-chainstate +or -reindex) to make sure your wallet has all the new data synced. Upgrading +from version 0.13 should not require any additional actions. + +When upgrading from a version prior to 18.0.1, the +first startup of Dash Core will run a migration process which can take anywhere +from a few minutes to thirty minutes to finish. After the migration, a +downgrade to an older version is only possible with a reindex +(or reindex-chainstate). + +Downgrade warning +----------------- + +### Downgrade to a version < v18.2.2 + +Downgrading to a version older than v18.2.2 is supported. + +### Downgrade to a version < v18.0.1 + +Downgrading to a version older than v18.0.1 is not supported due to changes in +the indexes database folder. If you need to use an older version, you must +either reindex or re-sync the whole chain. + +Notable changes +=============== + +Testnet Breaking Changes +------------------------ + +A new testnet only LLMQ has been added. This LLMQ is of the type LLMQ_25_67; this LLMQ is only active on testnet. +This LLMQ will not remove the LLMQ_100_67 from testnet; however that quorum (likely) will not form and will perform no role. +See the [diff](https://github.com/dashpay/dash/pull/5225/files#diff-e70a38a3e8c2a63ca0494627301a5c7042141ad301193f78338d97cb1b300ff9R451-R469) for specific parameters of the LLMQ. + +This LLMQ will become active at the height of 847000. **This will be a breaking change and a hard fork for testnet** +This LLMQ is not activated with the v19 hardfork; as such testnet will experience two hardforks. One at height 847000, +and the other to be determined by the BIP9 hard fork process. + +Remote Procedure Call (RPC) Changes +----------------------------------- + +### The new RPCs are: +None + +### The removed RPCs are: +None + +### Changes in existing RPCs introduced through bitcoin backports: +None + +### Dash-specific changes in existing RPCs: +None + +Please check `help ` for more detailed information on specific RPCs. + +Command-line options +-------------------- +None + +Please check `Help -> Command-line options` in Qt wallet or `dashd --help` for +more information. + +Backports from Bitcoin Core +--------------------------- +None + +Other changes +------------- +#5247 is backported to improve debugging experience. + +v18.2.2 Change log +================== + +See detailed [set of changes](https://github.com/dashpay/dash/compare/v18.2.1...dashpay:v18.2.2). + +Credits +======= + +Thanks to everyone who directly contributed to this release: + +- Odysseas Gabrielides +- UdjinM6 + +As well as everyone that submitted issues, reviewed pull requests, helped debug the release candidates, and write DIPs that were implemented in this release. + +Older releases +============== + +Dash was previously known as Darkcoin. + +Darkcoin tree 0.8.x was a fork of Litecoin tree 0.8, original name was XCoin +which was first released on Jan/18/2014. + +Darkcoin tree 0.9.x was the open source implementation of masternodes based on +the 0.8.x tree and was first released on Mar/13/2014. + +Darkcoin tree 0.10.x used to be the closed source implementation of Darksend +which was released open source on Sep/25/2014. + +Dash Core tree 0.11.x was a fork of Bitcoin Core tree 0.9, +Darkcoin was rebranded to Dash. + +Dash Core tree 0.12.0.x was a fork of Bitcoin Core tree 0.10. + +Dash Core tree 0.12.1.x was a fork of Bitcoin Core tree 0.12. + +These release are considered obsolete. Old release notes can be found here: + +- [v18.2.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.2.2.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 diff --git a/doc/release-notes/release-notes-20186.md b/doc/release-notes/release-notes-20186.md deleted file mode 100644 index f20ae08200..0000000000 --- a/doc/release-notes/release-notes-20186.md +++ /dev/null @@ -1,16 +0,0 @@ -Wallet ------- - -### Automatic wallet creation removed - -Dash Core will no longer automatically create new wallets on startup. It will -load existing wallets specified by `-wallet` options on the command line or in -`dash.conf` or `settings.json` files. And by default it will also load a -top-level unnamed ("") wallet. However, if specified wallets don't exist, -Dash Core will now just log warnings instead of creating new wallets with -new keys and addresses like previous releases did. - -New wallets can be created through the GUI (which has a more prominent create -wallet option), through the `dash-cli createwallet` or `dash-wallet -create` commands, or the `createwallet` RPC. -