Skip to content

Commit 3bac0a4

Browse files
Merge #6729: feat: prohibit new legacy scheme masternodes, restrict ProTx version changes with DEPLOYMENT_V23
af10784 doc: add release notes for version restrictions (Kittywhiskers Van Gogh) 991f14d evo: prohibit new legacy scheme masternode registrations (Kittywhiskers Van Gogh) abf96b5 evo: prohibit extended address versioning on unsupported transactions (Kittywhiskers Van Gogh) de7f928 evo: prohibit upgrading from LegacyBLS to ExtAddr support directly (Kittywhiskers Van Gogh) e430e6e evo: prohibit any ProTx with legacy BLS version after basic BLS upgrade (Kittywhiskers Van Gogh) dc687a9 rpc: constrain ProTx version for ProUpRevTx based on legacy status (Kittywhiskers Van Gogh) 23c5152 trivial: use consistent variable name, use brackets (Kittywhiskers Van Gogh) Pull request description: ## Additional Information * Depends on #6665 * Depends on #6723 * Please refer to comments from [dash#6665](#6665) for prior discussion on the contents of the pull request ([comment](#6665 (comment)), [comment](#6665 (comment)), [comment](#6665 (comment))) * Complementing the deprecation in [dash#6723](#6723), after `DEPLOYMENT_V23` is activated * Registration of **new** masternodes (i.e. `ProRegTx`) with the legacy scheme (`LegacyBLS`) will no longer be allowed. Existing masternodes are not affected and can continue to operate and participate. * Masternodes that are already using the basic scheme (`BasicBLS`) or higher may no longer **downgrade** to the legacy scheme. * Additional guardrails have been introduced to complement [dash#6665](#6665), which reserves a new version for extended addresses (`ExtAddr`), affecting `ProRegTx` and `ProUpServTx`, applicable after `DEPLOYMENT_V23` is activated * Masternodes **must** migrate to the basic scheme (`BasicBLS`) _before_ attempting to utilize extended addresses (`ExtAddr`), legacy scheme nodes may not attempt a direct upgrade. * Special transactions other than `ProRegTx` or `ProUpServTx` may not bear the version reserved for extended addresses (`ExtAddr`). Note that `IsVersionChangeValid()` does not extend to `ProRegTx` as it _creates_ a new entry and therefore doesn't have a masternode state version to compare against (i.e. there's no version to _change_), so the restriction in `IsVersionChangeValid()` only _de facto_ applies to `ProUpServTx`. * Future version updates must be conscious of updates to the masternode state ([source](https://github.com/dashpay/dash/blob/d9f52acecb94d57be91b5e17d478d5c909df3633/src/evo/deterministicmns.cpp#L887-L888)), example code for what changes may be required are available [here](#6665 (comment)). ## Breaking Changes * `protx revoke` will no longer default to using the highest possible version of `ProUpRevTx` and will now _clamp_ the version to `LegacyBLS` if the masternode uses the legacy scheme. ## 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 **(note: N/A)** - [x] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: PastaPastaPasta: utACK af10784 UdjinM6: utACK af10784 Tree-SHA512: fe788c33397f9e351377777946d5c0498569f68f22d308cce03f903fb3e149bd594ce2caafc50fd62611029563e2841bc42151579b21ba42fdf87cbf7762f716
2 parents dfbc639 + af10784 commit 3bac0a4

File tree

3 files changed

+79
-7
lines changed

3 files changed

+79
-7
lines changed

doc/release-notes-6729.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Notable Changes
2+
---------------
3+
4+
* Dash Core will no longer permit the registration of new legacy scheme masternodes after the deployment of the v23
5+
fork. Existing basic scheme masternodes will also be prohibited from downgrading to the legacy scheme after the
6+
deployment is active.
7+
8+
Updated RPCs
9+
----------------
10+
11+
* `protx revoke` will now use the legacy scheme version for legacy masternodes instead of the defaulting to the
12+
highest `ProUpRevTx` version.

src/evo/deterministicmns.cpp

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,41 @@ static std::optional<ProTx> GetValidatedPayload(const CTransaction& tx, gsl::not
957957
return opt_ptx;
958958
}
959959

960+
/**
961+
* Validates potential changes to masternode state version by ProTx transaction version
962+
* @param[in] pindexPrev Previous block index to validate DEPLOYMENT_V23 activation
963+
* @param[in] tx_type Special transaction type
964+
* @param[in] state_version Current masternode state version
965+
* @param[in] tx_version Proposed transaction version
966+
* @param[out] state This may be set to an Error state if any error occurred processing them
967+
* @returns true if version change is valid or DEPLOYMENT_V23 is not active
968+
*/
969+
bool IsVersionChangeValid(gsl::not_null<const CBlockIndex*> pindexPrev, const uint16_t tx_type,
970+
const uint16_t state_version, const uint16_t tx_version, TxValidationState& state)
971+
{
972+
if (!DeploymentActiveAfter(pindexPrev, Params().GetConsensus(), Consensus::DEPLOYMENT_V23)) {
973+
// New restrictions only apply after v23 deployment
974+
return true;
975+
}
976+
977+
if (state_version >= ProTxVersion::BasicBLS && tx_version == ProTxVersion::LegacyBLS) {
978+
// Don't allow legacy scheme versioned transactions after upgrading to basic scheme
979+
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-version-downgrade");
980+
}
981+
982+
if (state_version == ProTxVersion::LegacyBLS && tx_version > ProTxVersion::BasicBLS) {
983+
// Nodes using the legacy scheme must first upgrade to the basic scheme before upgrading further
984+
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-version-upgrade");
985+
}
986+
987+
if (tx_type != TRANSACTION_PROVIDER_UPDATE_SERVICE && tx_version == ProTxVersion::ExtAddr) {
988+
// Only new entries (ProRegTx) and service updates (ProUpServTx) can use ExtAddr versioning
989+
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-version-tx-type");
990+
}
991+
992+
return true;
993+
}
994+
960995
bool CheckProRegTx(CDeterministicMNManager& dmnman, const CTransaction& tx, gsl::not_null<const CBlockIndex*> pindexPrev, TxValidationState& state, const CCoinsViewCache& view, bool check_sigs)
961996
{
962997
const auto opt_ptx = GetValidatedPayload<CProRegTx>(tx, pindexPrev, state);
@@ -965,6 +1000,13 @@ bool CheckProRegTx(CDeterministicMNManager& dmnman, const CTransaction& tx, gsl:
9651000
return false;
9661001
}
9671002

1003+
const bool is_v23_active{DeploymentActiveAfter(pindexPrev, Params().GetConsensus(), Consensus::DEPLOYMENT_V23)};
1004+
1005+
// No longer allow legacy scheme masternode registration
1006+
if (is_v23_active && opt_ptx->nVersion < ProTxVersion::BasicBLS) {
1007+
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-version-disallowed");
1008+
}
1009+
9681010
// It's allowed to set addr to 0, which will put the MN into PoSe-banned state and require a ProUpServTx to be issues later
9691011
// If any of both is set, it must be valid however
9701012
if (!opt_ptx->netInfo->IsEmpty() && !CheckService(*opt_ptx, state)) {
@@ -1099,11 +1141,16 @@ bool CheckProUpServTx(CDeterministicMNManager& dmnman, const CTransaction& tx, g
10991141
}
11001142

11011143
auto mnList = dmnman.GetListForBlock(pindexPrev);
1102-
auto mn = mnList.GetMN(opt_ptx->proTxHash);
1103-
if (!mn) {
1144+
auto dmn = mnList.GetMN(opt_ptx->proTxHash);
1145+
if (!dmn) {
11041146
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-hash");
11051147
}
11061148

1149+
if (!IsVersionChangeValid(pindexPrev, tx.nType, dmn->pdmnState->nVersion, opt_ptx->nVersion, state)) {
1150+
// pass the state returned by the function above
1151+
return false;
1152+
}
1153+
11071154
// don't allow updating to addresses already used by other MNs
11081155
for (const NetInfoEntry& entry : opt_ptx->netInfo->GetEntries()) {
11091156
if (const auto& service_opt{entry.GetAddrPort()}; service_opt.has_value()) {
@@ -1124,7 +1171,7 @@ bool CheckProUpServTx(CDeterministicMNManager& dmnman, const CTransaction& tx, g
11241171
}
11251172

11261173
if (opt_ptx->scriptOperatorPayout != CScript()) {
1127-
if (mn->nOperatorReward == 0) {
1174+
if (dmn->nOperatorReward == 0) {
11281175
// don't allow setting operator reward payee in case no operatorReward was set
11291176
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-operator-payee");
11301177
}
@@ -1138,7 +1185,7 @@ bool CheckProUpServTx(CDeterministicMNManager& dmnman, const CTransaction& tx, g
11381185
// pass the state returned by the function above
11391186
return false;
11401187
}
1141-
if (check_sigs && !CheckHashSig(*opt_ptx, mn->pdmnState->pubKeyOperator.Get(), state)) {
1188+
if (check_sigs && !CheckHashSig(*opt_ptx, dmn->pdmnState->pubKeyOperator.Get(), state)) {
11421189
// pass the state returned by the function above
11431190
return false;
11441191
}
@@ -1166,6 +1213,11 @@ bool CheckProUpRegTx(CDeterministicMNManager& dmnman, const CTransaction& tx, gs
11661213
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-hash");
11671214
}
11681215

1216+
if (!IsVersionChangeValid(pindexPrev, tx.nType, dmn->pdmnState->nVersion, opt_ptx->nVersion, state)) {
1217+
// pass the state returned by the function above
1218+
return false;
1219+
}
1220+
11691221
// don't allow reuse of payee key for other keys (don't allow people to put the payee key onto an online server)
11701222
if (payoutDest == CTxDestination(PKHash(dmn->pdmnState->keyIDOwner)) || payoutDest == CTxDestination(PKHash(opt_ptx->keyIDVoting))) {
11711223
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-payee-reuse");
@@ -1221,8 +1273,14 @@ bool CheckProUpRevTx(CDeterministicMNManager& dmnman, const CTransaction& tx, gs
12211273

12221274
auto mnList = dmnman.GetListForBlock(pindexPrev);
12231275
auto dmn = mnList.GetMN(opt_ptx->proTxHash);
1224-
if (!dmn)
1276+
if (!dmn) {
12251277
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-hash");
1278+
}
1279+
1280+
if (!IsVersionChangeValid(pindexPrev, tx.nType, dmn->pdmnState->nVersion, opt_ptx->nVersion, state)) {
1281+
// pass the state returned by the function above
1282+
return false;
1283+
}
12261284

12271285
if (!CheckInputsHash(tx, *opt_ptx, state)) {
12281286
// pass the state returned by the function above

src/rpc/evo.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,14 +1269,16 @@ static RPCHelpMan protx_revoke()
12691269
EnsureWalletIsUnlocked(*pwallet);
12701270

12711271
CProUpRevTx ptx;
1272-
ptx.nVersion = ProTxVersion::GetMaxFromDeployment<CProUpRevTx>(WITH_LOCK(::cs_main, return chainman.ActiveChain().Tip()));
1273-
12741272
ptx.proTxHash = ParseHashV(request.params[0], "proTxHash");
1273+
12751274
auto dmn = dmnman.GetListAtChainTip().GetMN(ptx.proTxHash);
12761275
if (!dmn) {
12771276
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("masternode %s not found", ptx.proTxHash.ToString()));
12781277
}
12791278

1279+
ptx.nVersion = ProTxVersion::GetMaxFromDeployment<CProUpRevTx>(WITH_LOCK(::cs_main, return chainman.ActiveChain().Tip()),
1280+
/*is_basic_override=*/dmn->pdmnState->nVersion >= ProTxVersion::BasicBLS);
1281+
12801282
CBLSSecretKey keyOperator = ParseBLSSecretKey(request.params[1].get_str(), "operatorKey");
12811283

12821284
if (!request.params[2].isNull()) {

0 commit comments

Comments
 (0)