Skip to content

Commit 43318a4

Browse files
committed
rpc: extend the ability to withhold submission to all ProTxes
*Not* submitting a transaction gives test the ability to check if a call will result in a *valid* transaction, it also lets us examine the raw transaction, manipulate it and check if transaction checks at broadcast time will catch it. This is relevant for extended addresses (specifically, ProUpServTx) but has been extended to all ProTx-creating RPCs for consistency's sake.
1 parent 968698b commit 43318a4

File tree

5 files changed

+75
-39
lines changed

5 files changed

+75
-39
lines changed

src/rpc/evo.cpp

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ static void SignSpecialTxPayloadByHash(const CMutableTransaction& tx, SpecialTxP
320320
payload.sig = key.Sign(hash, use_legacy);
321321
}
322322

323-
static std::string SignAndSendSpecialTx(const JSONRPCRequest& request, CChainstateHelper& chain_helper, const ChainstateManager& chainman, const CMutableTransaction& tx, bool fSubmit = true)
323+
static std::string SignAndSendSpecialTx(const JSONRPCRequest& request, CChainstateHelper& chain_helper, const ChainstateManager& chainman, const CMutableTransaction& tx, bool fSubmit)
324324
{
325325
{
326326
LOCK(cs_main);
@@ -539,9 +539,9 @@ static RPCHelpMan protx_register_fund_evo()
539539
},
540540
{
541541
RPCResult{"if \"submit\" is not set or set to true",
542-
RPCResult::Type::STR_HEX, "txid", "The transaction id"},
542+
RPCResult::Type::STR_HEX, "txid", "The transaction id"},
543543
RPCResult{"if \"submit\" is set to false",
544-
RPCResult::Type::STR_HEX, "hex", "The serialized signed ProTx in hex format"},
544+
RPCResult::Type::STR_HEX, "hex", "The serialized signed ProTx in hex format"},
545545
},
546546
RPCExamples{
547547
HelpExampleCli("protx", "register_fund_evo \"" + EXAMPLE_ADDRESS[0] + "\" \"1.2.3.4:1234\" \"" + EXAMPLE_ADDRESS[1] + "\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"" + EXAMPLE_ADDRESS[1] + "\" 0 \"" + EXAMPLE_ADDRESS[0] + "\" \"f2dbd9b0a1f541a7c44d34a58674d0262f5feca5\" 22821 22822")},
@@ -578,9 +578,9 @@ static RPCHelpMan protx_register_evo()
578578
},
579579
{
580580
RPCResult{"if \"submit\" is not set or set to true",
581-
RPCResult::Type::STR_HEX, "txid", "The transaction id"},
581+
RPCResult::Type::STR_HEX, "txid", "The transaction id"},
582582
RPCResult{"if \"submit\" is set to false",
583-
RPCResult::Type::STR_HEX, "hex", "The serialized signed ProTx in hex format"},
583+
RPCResult::Type::STR_HEX, "hex", "The serialized signed ProTx in hex format"},
584584
},
585585
RPCExamples{
586586
HelpExampleCli("protx", "register_evo \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"" + EXAMPLE_ADDRESS[1] + "\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"" + EXAMPLE_ADDRESS[1] + "\" 0 \"" + EXAMPLE_ADDRESS[0] + "\" \"f2dbd9b0a1f541a7c44d34a58674d0262f5feca5\" 22821 22822")},
@@ -885,7 +885,7 @@ static RPCHelpMan protx_register_submit()
885885
ptx.vchSig = opt_vchSig.value();
886886

887887
SetTxPayload(tx, ptx);
888-
return SignAndSendSpecialTx(request, chain_helper, chainman, tx);
888+
return SignAndSendSpecialTx(request, chain_helper, chainman, tx, /*fSubmit=*/true);
889889
},
890890
};
891891
}
@@ -903,9 +903,13 @@ static RPCHelpMan protx_update_service()
903903
GetRpcArg("operatorKey"),
904904
GetRpcArg("operatorPayoutAddress"),
905905
GetRpcArg("feeSourceAddress"),
906+
GetRpcArg("submit"),
906907
},
907-
RPCResult{
908-
RPCResult::Type::STR_HEX, "txid", "The transaction id"
908+
{
909+
RPCResult{"if \"submit\" is not set or set to true",
910+
RPCResult::Type::STR_HEX, "txid", "The transaction id"},
911+
RPCResult{"if \"submit\" is set to false",
912+
RPCResult::Type::STR_HEX, "hex", "The serialized signed ProTx in hex format"},
909913
},
910914
RPCExamples{
911915
HelpExampleCli("protx", "update_service \"0123456701234567012345670123456701234567012345670123456701234567\" \"1.2.3.4:1234\" 5a2e15982e62f1e0b7cf9783c64cf7e3af3f90a52d6c40f6f95d624c0b1621cd")
@@ -935,9 +939,14 @@ static RPCHelpMan protx_update_service_evo()
935939
GetRpcArg("platformHTTPPort"),
936940
GetRpcArg("operatorPayoutAddress"),
937941
GetRpcArg("feeSourceAddress"),
942+
GetRpcArg("submit"),
943+
},
944+
{
945+
RPCResult{"if \"submit\" is not set or set to true",
946+
RPCResult::Type::STR_HEX, "txid", "The transaction id"},
947+
RPCResult{"if \"submit\" is set to false",
948+
RPCResult::Type::STR_HEX, "hex", "The serialized signed ProTx in hex format"},
938949
},
939-
RPCResult{
940-
RPCResult::Type::STR_HEX, "txid", "The transaction id"},
941950
RPCExamples{
942951
HelpExampleCli("protx", "update_service_evo \"0123456701234567012345670123456701234567012345670123456701234567\" \"1.2.3.4:1234\" \"5a2e15982e62f1e0b7cf9783c64cf7e3af3f90a52d6c40f6f95d624c0b1621cd\" \"f2dbd9b0a1f541a7c44d34a58674d0262f5feca5\" 22821 22822")},
943952
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
@@ -1043,14 +1052,19 @@ static UniValue protx_update_service_common_wrapper(const JSONRPCRequest& reques
10431052
}
10441053
}
10451054

1055+
bool fSubmit{true};
1056+
if (!request.params[paramIdx + 2].isNull()) {
1057+
fSubmit = ParseBoolV(request.params[paramIdx + 2], "submit");
1058+
}
1059+
10461060
FundSpecialTx(*wallet, tx, ptx, feeSource);
10471061

10481062
const bool isV19active = DeploymentActiveAfter(WITH_LOCK(cs_main, return chainman.ActiveChain().Tip();),
10491063
Params().GetConsensus(), Consensus::DEPLOYMENT_V19);
10501064
SignSpecialTxPayloadByHash(tx, ptx, keyOperator, !isV19active);
10511065
SetTxPayload(tx, ptx);
10521066

1053-
return SignAndSendSpecialTx(request, chain_helper, chainman, tx);
1067+
return SignAndSendSpecialTx(request, chain_helper, chainman, tx, fSubmit);
10541068
}
10551069

10561070
static RPCHelpMan protx_update_registrar_wrapper(const bool specific_legacy_bls_scheme)
@@ -1070,9 +1084,13 @@ static RPCHelpMan protx_update_registrar_wrapper(const bool specific_legacy_bls_
10701084
GetRpcArg("votingAddress_update"),
10711085
GetRpcArg("payoutAddress_update"),
10721086
GetRpcArg("feeSourceAddress"),
1087+
GetRpcArg("submit"),
10731088
},
1074-
RPCResult{
1075-
RPCResult::Type::STR_HEX, "txid", "The transaction id"
1089+
{
1090+
RPCResult{"if \"submit\" is not set or set to true",
1091+
RPCResult::Type::STR_HEX, "txid", "The transaction id"},
1092+
RPCResult{"if \"submit\" is set to false",
1093+
RPCResult::Type::STR_HEX, "hex", "The serialized signed ProTx in hex format"},
10761094
},
10771095
RPCExamples{
10781096
HelpExampleCli("protx", rpc_example)
@@ -1149,11 +1167,16 @@ static RPCHelpMan protx_update_registrar_wrapper(const bool specific_legacy_bls_
11491167
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + request.params[4].get_str());
11501168
}
11511169

1170+
bool fSubmit{true};
1171+
if (!request.params[5].isNull()) {
1172+
fSubmit = ParseBoolV(request.params[5], "submit");
1173+
}
1174+
11521175
FundSpecialTx(*wallet, tx, ptx, feeSourceDest);
11531176
SignSpecialTxPayloadByHash(tx, ptx, dmn->pdmnState->keyIDOwner, *wallet);
11541177
SetTxPayload(tx, ptx);
11551178

1156-
return SignAndSendSpecialTx(request, chain_helper, chainman, tx);
1179+
return SignAndSendSpecialTx(request, chain_helper, chainman, tx, fSubmit);
11571180
},
11581181
};
11591182
}
@@ -1181,9 +1204,13 @@ static RPCHelpMan protx_revoke()
11811204
GetRpcArg("operatorKey"),
11821205
GetRpcArg("reason"),
11831206
GetRpcArg("feeSourceAddress"),
1207+
GetRpcArg("submit"),
11841208
},
1185-
RPCResult{
1186-
RPCResult::Type::STR_HEX, "txid", "The transaction id"
1209+
{
1210+
RPCResult{"if \"submit\" is not set or set to true",
1211+
RPCResult::Type::STR_HEX, "txid", "The transaction id"},
1212+
RPCResult{"if \"submit\" is set to false",
1213+
RPCResult::Type::STR_HEX, "hex", "The serialized signed ProTx in hex format"},
11871214
},
11881215
RPCExamples{
11891216
HelpExampleCli("protx", "revoke \"0123456701234567012345670123456701234567012345670123456701234567\" \"072f36a77261cdd5d64c32d97bac417540eddca1d5612f416feb07ff75a8e240\"")
@@ -1248,10 +1275,15 @@ static RPCHelpMan protx_revoke()
12481275
throw JSONRPCError(RPC_INTERNAL_ERROR, "No payout or fee source addresses found, can't revoke");
12491276
}
12501277

1278+
bool fSubmit{true};
1279+
if (!request.params[4].isNull()) {
1280+
fSubmit = ParseBoolV(request.params[4], "submit");
1281+
}
1282+
12511283
SignSpecialTxPayloadByHash(tx, ptx, keyOperator, !isV19active);
12521284
SetTxPayload(tx, ptx);
12531285

1254-
return SignAndSendSpecialTx(request, chain_helper, chainman, tx);
1286+
return SignAndSendSpecialTx(request, chain_helper, chainman, tx, fSubmit);
12551287
},
12561288
};
12571289
}

test/functional/feature_dip3_deterministicmns.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ def run_test(self):
213213
assert old_voting_address != new_voting_address
214214
# also check if funds from payout address are used when no fee source address is specified
215215
node.sendtoaddress(mn.rewards_address, 0.001)
216-
mn.update_registrar(node, pubKeyOperator="", votingAddr=new_voting_address, rewards_address="")
216+
mn.update_registrar(node, submit=True, pubKeyOperator="", votingAddr=new_voting_address, rewards_address="")
217217
self.generate(node, 1)
218218
new_dmnState = mn.get_node(self).masternode("status")["dmnState"]
219219
new_voting_address_from_rpc = new_dmnState["votingAddress"]
@@ -237,14 +237,14 @@ def create_mn_collateral(self, node, mn: MasternodeInfo):
237237
# register a protx MN and also fund it (using collateral inside ProRegTx)
238238
def register_fund_mn(self, node, mn: MasternodeInfo):
239239
node.sendtoaddress(mn.fundsAddr, mn.get_collateral_value() + 0.001)
240-
txid = mn.register_fund(node, True)
240+
txid = mn.register_fund(node, submit=True)
241241
vout = mn.get_collateral_vout(node, txid)
242242
mn.set_params(proTxHash=txid, collateral_txid=txid, collateral_vout=vout)
243243

244244
# create a protx MN which refers to an existing collateral
245245
def register_mn(self, node, mn: MasternodeInfo):
246246
node.sendtoaddress(mn.fundsAddr, 0.001)
247-
proTxHash = mn.register(node, True)
247+
proTxHash = mn.register(node, submit=True)
248248
mn.set_params(proTxHash=proTxHash)
249249
self.generate(node, 1, sync_fun=self.no_op)
250250

@@ -263,14 +263,14 @@ def spend_mn_collateral(self, mn: MasternodeInfo, with_dummy_input_output=False)
263263

264264
def update_mn_payee(self, mn: MasternodeInfo, payee):
265265
self.nodes[0].sendtoaddress(mn.fundsAddr, 0.001)
266-
mn.update_registrar(self.nodes[0], pubKeyOperator="", votingAddr="", rewards_address=payee, fundsAddr=mn.fundsAddr)
266+
mn.update_registrar(self.nodes[0], submit=True, pubKeyOperator="", votingAddr="", rewards_address=payee, fundsAddr=mn.fundsAddr)
267267
self.generate(self.nodes[0], 1)
268268
info = self.nodes[0].protx('info', mn.proTxHash)
269269
assert info['state']['payoutAddress'] == payee
270270

271271
def test_protx_update_service(self, mn: MasternodeInfo):
272272
self.nodes[0].sendtoaddress(mn.fundsAddr, 0.001)
273-
mn.update_service(self.nodes[0], ipAndPort=f'127.0.0.2:{mn.nodePort}')
273+
mn.update_service(self.nodes[0], submit=True, ipAndPort=f'127.0.0.2:{mn.nodePort}')
274274
self.generate(self.nodes[0], 1)
275275
for node in self.nodes:
276276
protx_info = node.protx('info', mn.proTxHash)
@@ -279,7 +279,7 @@ def test_protx_update_service(self, mn: MasternodeInfo):
279279
assert_equal(mn_list['%s-%d' % (mn.collateral_txid, mn.collateral_vout)]['address'], '127.0.0.2:%d' % mn.nodePort)
280280

281281
# undo
282-
mn.update_service(self.nodes[0])
282+
mn.update_service(self.nodes[0], submit=True)
283283
self.generate(self.nodes[0], 1, sync_fun=self.no_op)
284284

285285
def assert_mnlists(self, mns):

test/functional/feature_dip3_v19.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def test_revoke_protx(self, node_idx, revoke_mn: MasternodeInfo):
120120
tip = self.generate(self.nodes[0], 1)[0]
121121
assert_equal(self.nodes[0].getrawtransaction(fund_txid, 1, tip)['confirmations'], 1)
122122

123-
protx_result = revoke_mn.revoke(self.nodes[0], reason=1, fundsAddr=funds_address)
123+
protx_result = revoke_mn.revoke(self.nodes[0], submit=True, reason=1, fundsAddr=funds_address)
124124
self.bump_mocktime(10 * 60 + 1) # to make tx safe to include in block
125125
tip = self.generate(self.nodes[0], 1, sync_fun=self.no_op)[0]
126126
assert_equal(self.nodes[0].getrawtransaction(protx_result, 1, tip)['confirmations'], 1)

test/functional/feature_llmq_simplepose.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ def repair_masternodes(self, restart):
208208
if check_banned(self.nodes[0], mn) or check_punished(self.nodes[0], mn):
209209
addr = self.nodes[0].getnewaddress()
210210
self.nodes[0].sendtoaddress(addr, 0.1)
211-
mn.update_service(self.nodes[0], fundsAddr=addr)
211+
mn.update_service(self.nodes[0], submit=True, fundsAddr=addr)
212212
if restart:
213213
self.stop_node(mn.nodeIdx)
214214
self.start_masternode(mn)

0 commit comments

Comments
 (0)