Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 25 additions & 21 deletions src/evo/providertx_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,23 @@ PayoutResult BuildPayouts(const std::vector<ProviderPayout>& payouts)
return result;
}

std::optional<ProviderTxError> ResolveFeeSource(const std::optional<CTxDestination>& fee_source,
const CScript& operator_payout, const CDeterministicMNState& dmn_state,
std::string missing_error, CTxDestination& fund_destination)
{
if (fee_source) {
fund_destination = *fee_source;
} else if (!operator_payout.empty()) {
ExtractDestination(operator_payout, fund_destination);
} else {
const auto owner_payouts{GetOwnerPayouts(dmn_state)};
if (owner_payouts.empty() || !ExtractDestination(owner_payouts.front().scriptPayout, fund_destination)) {
return Error(ProviderTxErrorCode::INVALID_PARAMETER, std::move(missing_error));
}
}
return std::nullopt;
}

template <typename Payload>
void UpdateInputsHash(const CMutableTransaction& tx, Payload& payload)
{
Expand Down Expand Up @@ -436,7 +453,7 @@ RegistrationResult BuildRegistration(node::NodeContext& node, Wallet& wallet,
if (const auto* collateral{std::get_if<FundProviderCollateral>(&request.collateral)}) {
if (!IsValidDestination(collateral->destination)) {
return Error(ProviderTxErrorCode::INVALID_ADDRESS_OR_KEY,
strprintf("invalid collaterall address: %s", EncodeDestination(collateral->destination)));
strprintf("invalid collateral address: %s", EncodeDestination(collateral->destination)));
}
tx.vout.emplace_back(GetMnType(request.type).collat_amount, GetScriptForDestination(collateral->destination));
} else {
Expand Down Expand Up @@ -675,16 +692,10 @@ ProviderTxResult<ProviderTxSubmission> UpdateService(node::NodeContext& node, Wa
: dmn->pdmnState->scriptOperatorPayout;

CTxDestination fund_destination;
if (request.fee_source) {
fund_destination = *request.fee_source;
} else if (!payload.scriptOperatorPayout.empty()) {
ExtractDestination(payload.scriptOperatorPayout, fund_destination);
} else {
const auto owner_payouts{GetOwnerPayouts(*dmn->pdmnState)};
if (owner_payouts.empty() || !ExtractDestination(owner_payouts.front().scriptPayout, fund_destination)) {
return Error(ProviderTxErrorCode::INVALID_PARAMETER,
"masternode has no default fee source; specify feeSourceAddress");
}
if (auto error{ResolveFeeSource(request.fee_source, payload.scriptOperatorPayout, *dmn->pdmnState,
"masternode has no default fee source; specify feeSourceAddress",
fund_destination)}) {
return *error;
}

CMutableTransaction tx;
Expand Down Expand Up @@ -798,16 +809,9 @@ ProviderTxResult<ProviderTxSubmission> Revoke(node::NodeContext& node, Wallet& w
payload.nReason = request.reason;

CTxDestination fund_destination;
if (request.fee_source) {
fund_destination = *request.fee_source;
} else if (!dmn->pdmnState->scriptOperatorPayout.empty()) {
ExtractDestination(dmn->pdmnState->scriptOperatorPayout, fund_destination);
} else {
const auto owner_payouts{GetOwnerPayouts(*dmn->pdmnState)};
if (owner_payouts.empty() || !ExtractDestination(owner_payouts.front().scriptPayout, fund_destination)) {
return Error(ProviderTxErrorCode::INVALID_PARAMETER,
"No payout or fee source addresses found, can't revoke");
}
if (auto error{ResolveFeeSource(request.fee_source, dmn->pdmnState->scriptOperatorPayout, *dmn->pdmnState,
"No payout or fee source addresses found, can't revoke", fund_destination)}) {
return *error;
}

CMutableTransaction tx;
Expand Down
85 changes: 32 additions & 53 deletions src/rpc/evo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <walletinitinterface.h>

#include <limits>
#include <optional>
#include <string_view>

#ifdef ENABLE_WALLET
Expand Down Expand Up @@ -392,6 +393,23 @@ static std::string SubmissionToString(const interfaces::ProviderTxSubmission& su
return submission.submitted ? submission.tx->GetHash().GetHex() : EncodeHexTx(*submission.tx);
}

template <typename T>
static T UnwrapOrThrow(interfaces::ProviderTxResult<T> result)
{
if (const auto* error{std::get_if<interfaces::ProviderTxError>(&result)}) ThrowProviderTxError(*error);
return std::get<T>(std::move(result));
}

static std::optional<CTxDestination> ParseFeeSource(const UniValue& param)
{
if (param.isNull()) return std::nullopt;
CTxDestination fee_source{DecodeDestination(param.get_str())};
if (!IsValidDestination(fee_source)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + param.get_str());
}
return fee_source;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

static std::vector<std::string> ParseCoreNetInfo(const UniValue& input, bool optional)
{
if (input.isStr()) {
Expand Down Expand Up @@ -469,7 +487,7 @@ enum class ProTxRegisterAction
Fund,
Prepare,
};
} // anonumous namespace
} // anonymous namespace

static UniValue protx_register_common_wrapper(const JSONRPCRequest& request,
const bool specific_legacy_bls_scheme,
Expand Down Expand Up @@ -769,7 +787,7 @@ static UniValue protx_register_common_wrapper(const JSONRPCRequest& request,
CTxDestination collateral_destination{DecodeDestination(request.params[paramIdx].get_str())};
if (!IsValidDestination(collateral_destination)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
strprintf("invalid collaterall address: %s", request.params[paramIdx].get_str()));
strprintf("invalid collateral address: %s", request.params[paramIdx].get_str()));
}
typed_request.collateral = interfaces::FundProviderCollateral{collateral_destination};
paramIdx++;
Expand Down Expand Up @@ -823,33 +841,22 @@ static UniValue protx_register_common_wrapper(const JSONRPCRequest& request,
paramIdx += 3;
}

if (!request.params[paramIdx + 6].isNull()) {
CTxDestination fund_destination{DecodeDestination(request.params[paramIdx + 6].get_str())};
if (!IsValidDestination(fund_destination)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
std::string("Invalid Dash address: ") + request.params[paramIdx + 6].get_str());
}
typed_request.fee_source = fund_destination;
}
typed_request.fee_source = ParseFeeSource(request.params[paramIdx + 6]);
if ((action == ProTxRegisterAction::External || action == ProTxRegisterAction::Fund) &&
!request.params[paramIdx + 7].isNull()) {
typed_request.submit = ParseBoolV(request.params[paramIdx + 7], "submit");
}

auto wallet_interface{MakeWalletInterface(node, pwallet)};
if (action == ProTxRegisterAction::Prepare) {
auto result{evo::provider::PrepareRegistration(node, *wallet_interface, typed_request)};
if (const auto* error{std::get_if<interfaces::ProviderTxError>(&result)}) ThrowProviderTxError(*error);
const auto& prepared{std::get<interfaces::PreparedProviderRegistration>(result)};
const auto prepared{UnwrapOrThrow(evo::provider::PrepareRegistration(node, *wallet_interface, typed_request))};
UniValue response{UniValue::VOBJ};
response.pushKV("tx", EncodeHexTx(*prepared.tx));
response.pushKV("collateralAddress", EncodeDestination(prepared.collateral_address));
response.pushKV("signMessage", prepared.sign_message);
return response;
}
auto result{evo::provider::Register(node, *wallet_interface, typed_request)};
if (const auto* error{std::get_if<interfaces::ProviderTxError>(&result)}) ThrowProviderTxError(*error);
return SubmissionToString(std::get<interfaces::ProviderTxSubmission>(result));
return SubmissionToString(UnwrapOrThrow(evo::provider::Register(node, *wallet_interface, typed_request)));
}

static RPCHelpMan protx_register_submit()
Expand Down Expand Up @@ -883,10 +890,8 @@ static RPCHelpMan protx_register_submit()
}

auto wallet_interface{MakeWalletInterface(node, wallet)};
auto result{evo::provider::SubmitRegistration(node, *wallet_interface, MakeTransactionRef(std::move(tx)),
*opt_vchSig)};
if (const auto* error{std::get_if<interfaces::ProviderTxError>(&result)}) ThrowProviderTxError(*error);
return SubmissionToString(std::get<interfaces::ProviderTxSubmission>(result));
return SubmissionToString(UnwrapOrThrow(evo::provider::SubmitRegistration(
node, *wallet_interface, MakeTransactionRef(std::move(tx)), *opt_vchSig)));
},
};
}
Expand Down Expand Up @@ -994,22 +999,13 @@ static UniValue protx_update_service_common_wrapper(const JSONRPCRequest& reques
}
typed_request.operator_payout = payout_destination;
}
if (!request.params[paramIdx + 1].isNull()) {
CTxDestination fee_source{DecodeDestination(request.params[paramIdx + 1].get_str())};
if (!IsValidDestination(fee_source)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
std::string("Invalid Dash address: ") + request.params[paramIdx + 1].get_str());
}
typed_request.fee_source = fee_source;
}
typed_request.fee_source = ParseFeeSource(request.params[paramIdx + 1]);
if (!request.params[paramIdx + 2].isNull()) {
typed_request.submit = ParseBoolV(request.params[paramIdx + 2], "submit");
}

auto wallet_interface{MakeWalletInterface(node, wallet)};
auto result{evo::provider::UpdateService(node, *wallet_interface, typed_request)};
if (const auto* error{std::get_if<interfaces::ProviderTxError>(&result)}) ThrowProviderTxError(*error);
return SubmissionToString(std::get<interfaces::ProviderTxSubmission>(result));
return SubmissionToString(UnwrapOrThrow(evo::provider::UpdateService(node, *wallet_interface, typed_request)));
}

static RPCHelpMan protx_update_registrar_wrapper(const bool specific_legacy_bls_scheme)
Expand Down Expand Up @@ -1070,22 +1066,14 @@ static RPCHelpMan protx_update_registrar_wrapper(const bool specific_legacy_bls_
}
typed_request.payouts = ParsePayouts(request.params[3], "payouts");
}
if (!request.params[4].isNull()) {
CTxDestination fee_source{DecodeDestination(request.params[4].get_str())};
if (!IsValidDestination(fee_source)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
std::string("Invalid Dash address: ") + request.params[4].get_str());
}
typed_request.fee_source = fee_source;
}
typed_request.fee_source = ParseFeeSource(request.params[4]);
if (!request.params[5].isNull()) {
typed_request.submit = ParseBoolV(request.params[5], "submit");
}

auto wallet_interface{MakeWalletInterface(node, wallet)};
auto result{evo::provider::UpdateRegistrar(node, *wallet_interface, typed_request)};
if (const auto* error{std::get_if<interfaces::ProviderTxError>(&result)}) ThrowProviderTxError(*error);
return SubmissionToString(std::get<interfaces::ProviderTxSubmission>(result));
return SubmissionToString(
UnwrapOrThrow(evo::provider::UpdateRegistrar(node, *wallet_interface, typed_request)));
},
};
}
Expand Down Expand Up @@ -1141,22 +1129,13 @@ static RPCHelpMan protx_revoke()
}
typed_request.reason = static_cast<uint16_t>(nReason);
}
if (!request.params[3].isNull()) {
CTxDestination fee_source{DecodeDestination(request.params[3].get_str())};
if (!IsValidDestination(fee_source)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
std::string("Invalid Dash address: ") + request.params[3].get_str());
}
typed_request.fee_source = fee_source;
}
typed_request.fee_source = ParseFeeSource(request.params[3]);
if (!request.params[4].isNull()) {
typed_request.submit = ParseBoolV(request.params[4], "submit");
}

auto wallet_interface{MakeWalletInterface(node, pwallet)};
auto result{evo::provider::Revoke(node, *wallet_interface, typed_request)};
if (const auto* error{std::get_if<interfaces::ProviderTxError>(&result)}) ThrowProviderTxError(*error);
return SubmissionToString(std::get<interfaces::ProviderTxSubmission>(result));
return SubmissionToString(UnwrapOrThrow(evo::provider::Revoke(node, *wallet_interface, typed_request)));
},
};
}
Expand Down
2 changes: 1 addition & 1 deletion test/util/data/non-backported.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ src/index/spent*.cpp
src/index/spent*.h
src/index/timestamp*.cpp
src/index/timestamp*.h
src/interfaces/providertx.h
src/instantsend/*.cpp
src/instantsend/*.h
src/interfaces/providertx.h
src/llmq/*.cpp
src/llmq/*.h
src/masternode/*.cpp
Expand Down