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
6 changes: 4 additions & 2 deletions src/blockassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
CWallet* pwallet,
bool fProofOfStake,
std::vector<CStakeableOutput>* availableCoins,
bool fNoMempoolTx)
bool fNoMempoolTx,
bool fTestValidity)
{
resetBlock();

Expand Down Expand Up @@ -242,7 +243,8 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
if (chainActive.Tip() != pindexPrev) return nullptr; // new block came in, move on

CValidationState state;
if (!TestBlockValidity(state, *pblock, pindexPrev, false, false, false)) {
if (fTestValidity &&
!TestBlockValidity(state, *pblock, pindexPrev, false, false, false)) {
throw std::runtime_error(
strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
}
Expand Down
3 changes: 2 additions & 1 deletion src/blockassembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ class BlockAssembler
CWallet* pwallet = nullptr,
bool fProofOfStake = false,
std::vector<CStakeableOutput>* availableCoins = nullptr,
bool fNoMempoolTx = false);
bool fNoMempoolTx = false,
bool fTestValidity = true);

private:
// utility functions
Expand Down
45 changes: 32 additions & 13 deletions src/budget/budgetmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ std::string CBudgetManager::GetFinalizedBudgetStatus(const uint256& nHash) const
return retBadHashes + " -- " + retBadPayeeOrAmount;
}

bool CBudgetManager::AddFinalizedBudget(CFinalizedBudget& finalizedBudget)
bool CBudgetManager::AddFinalizedBudget(CFinalizedBudget& finalizedBudget, CNode* pfrom)
{
AssertLockNotHeld(cs_budgets); // need to lock cs_main here (CheckCollateral)
const uint256& nHash = finalizedBudget.GetHash();
Expand Down Expand Up @@ -222,6 +222,25 @@ bool CBudgetManager::AddFinalizedBudget(CFinalizedBudget& finalizedBudget)
return false;
}

// Compare budget payments with existent proposals, don't care on the order, just verify proposals existence.
std::vector<CBudgetProposal> vBudget = GetBudget();
std::map<uint256, CBudgetProposal> mapWinningProposals;
for (const CBudgetProposal& p: vBudget) { mapWinningProposals.emplace(p.GetHash(), p); }
if (!finalizedBudget.CheckProposals(mapWinningProposals)) {
finalizedBudget.SetStrInvalid("Invalid proposals");
LogPrint(BCLog::MNBUDGET,"%s: Budget finalization does not match with winning proposals\n", __func__);
// just for now (until v6), request proposals sync in case we are missing one of them.
if (pfrom) {
for (const auto& propId : finalizedBudget.GetProposalsHashes()) {
if (!g_budgetman.HaveProposal(propId)) {
pfrom->PushInventory(CInv(MSG_BUDGET_PROPOSAL, propId));
}
}
}
return false;
}

// Add budget finalization.
SetBudgetProposalsStr(finalizedBudget);
ForceAddFinalizedBudget(nHash, feeTxId, finalizedBudget);

Expand Down Expand Up @@ -632,19 +651,19 @@ TrxValidationStatus CBudgetManager::IsTransactionValid(const CTransaction& txNew
bool fThreshold = false;
{
LOCK(cs_budgets);
for (const auto& it: mapFinalizedBudgets) {
const CFinalizedBudget* pfb = &(it.second);
const int nVoteCount = pfb->GetVoteCount();
LogPrint(BCLog::MNBUDGET,"%s: checking %s (%s): votes %d (threshold %d)\n",
__func__, pfb->GetName(), pfb->GetProposalsStr(), nVoteCount, nCountThreshold);
if (nVoteCount > nCountThreshold) {
// Get the finalized budget with the highest amount of votes..
const CFinalizedBudget* highestVotesBudget = GetBudgetWithHighestVoteCount(nBlockHeight);
if (highestVotesBudget) {
// Need to surpass the threshold
if (highestVotesBudget->GetVoteCount() > nCountThreshold) {
fThreshold = true;
if (pfb->IsTransactionValid(txNew, nBlockHash, nBlockHeight) == TrxValidationStatus::Valid) {
if (highestVotesBudget->IsTransactionValid(txNew, nBlockHash, nBlockHeight) ==
TrxValidationStatus::Valid) {
return TrxValidationStatus::Valid;
}
// tx not valid. keep looking.
LogPrint(BCLog::MNBUDGET, "%s: ignoring budget. Out of range or tx not valid.\n", __func__);
}
// tx not valid
LogPrint(BCLog::MNBUDGET, "%s: ignoring budget. Out of range or tx not valid.\n", __func__);
}
}

Expand Down Expand Up @@ -1049,15 +1068,15 @@ bool CBudgetManager::ProcessProposalVote(CBudgetVote& vote, CNode* pfrom, CValid
return true;
}

int CBudgetManager::ProcessFinalizedBudget(CFinalizedBudget& finalbudget)
int CBudgetManager::ProcessFinalizedBudget(CFinalizedBudget& finalbudget, CNode* pfrom)
{

const uint256& nHash = finalbudget.GetHash();
if (HaveFinalizedBudget(nHash)) {
masternodeSync.AddedBudgetItem(nHash);
return 0;
}
if (!AddFinalizedBudget(finalbudget)) {
if (!AddFinalizedBudget(finalbudget, pfrom)) {
return 0;
}
finalbudget.Relay();
Expand Down Expand Up @@ -1195,7 +1214,7 @@ int CBudgetManager::ProcessMessageInner(CNode* pfrom, std::string& strCommand, C
if (!finalbudget.ParseBroadcast(vRecv)) {
return 20;
}
return ProcessFinalizedBudget(finalbudget);
return ProcessFinalizedBudget(finalbudget, pfrom);
}

if (strCommand == NetMsgType::FINALBUDGETVOTE) {
Expand Down
4 changes: 2 additions & 2 deletions src/budget/budgetmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class CBudgetManager

int ProcessBudgetVoteSync(const uint256& nProp, CNode* pfrom);
int ProcessProposal(CBudgetProposal& proposal);
int ProcessFinalizedBudget(CFinalizedBudget& finalbudget);
int ProcessFinalizedBudget(CFinalizedBudget& finalbudget, CNode* pfrom);

bool ProcessProposalVote(CBudgetVote& proposal, CNode* pfrom, CValidationState& state);
bool ProcessFinalizedBudgetVote(CFinalizedBudgetVote& vote, CNode* pfrom, CValidationState& state);
Expand All @@ -121,7 +121,7 @@ class CBudgetManager
bool IsBudgetPaymentBlock(int nBlockHeight) const;
bool IsBudgetPaymentBlock(int nBlockHeight, int& nCountThreshold) const;
bool AddProposal(CBudgetProposal& budgetProposal);
bool AddFinalizedBudget(CFinalizedBudget& finalizedBudget);
bool AddFinalizedBudget(CFinalizedBudget& finalizedBudget, CNode* pfrom = nullptr);
void ForceAddFinalizedBudget(const uint256& nHash, const uint256& feeTxId, const CFinalizedBudget& finalizedBudget);
uint256 SubmitFinalBudget();

Expand Down
88 changes: 88 additions & 0 deletions src/rpc/budget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,93 @@ UniValue mnfinalbudgetsuggest(const JSONRPCRequest& request)
return (budgetHash.IsNull()) ? NullUniValue : budgetHash.ToString();
}

UniValue createrawmnfinalbudget(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 4)
throw std::runtime_error(
"createrawmnfinalbudget\n"
"\nTry to submit the raw budget finalization\n"
"returns the budget hash if it was broadcasted sucessfully"
"\nArguments:\n"
"1. \"budgetname\" (string, required) finalization name\n"
"2. \"blockstart\" (numeric, required) superblock height\n"
"3. \"proposals\" (string, required) A json array of json objects\n"
" [\n"
" {\n"
" \"proposalid\":\"id\", (string, required) The proposal id\n"
" \"payee\":n, (hex, required) The payee script\n"
" \"amount\":n (numeric, optional) The payee amount\n"
" }\n"
" ,...\n"
" ]\n"
"4. \"feetxid\" (string, optional) the transaction fee hash\n"
""
"\nResult:\n"
"{\n"
"\"result\" (string) Budget suggest broadcast or error\n"
"\"id\" (string) id of the fee tx or the finalized budget\n"
"}\n"
); // future: add examples.

if (!Params().IsRegTestNet()) {
throw JSONRPCError(RPC_MISC_ERROR, "command available only for RegTest network");
}

// future: add inputs error checking..
std::string budName = request.params[0].get_str();
int nBlockStart = request.params[1].get_int();
std::vector<CTxBudgetPayment> vecTxBudgetPayments;
UniValue budgetVec = request.params[2].get_array();
for (unsigned int idx = 0; idx < budgetVec.size(); idx++) {
const UniValue& prop = budgetVec[idx].get_obj();
uint256 propId = ParseHashO(prop, "proposalid");
std::vector<unsigned char> scriptData(ParseHexO(prop, "payee"));
CScript payee = CScript(scriptData.begin(), scriptData.end());
CAmount amount = AmountFromValue(find_value(prop, "amount"));
vecTxBudgetPayments.emplace_back(propId, payee, amount);
}

Optional<uint256> txFeeId = nullopt;
if (request.params.size() > 3) {
txFeeId = ParseHashV(request.params[3], "parameter 4");
}

if (!txFeeId) {
CFinalizedBudget tempBudget(budName, nBlockStart, vecTxBudgetPayments, UINT256_ZERO);
const uint256& budgetHash = tempBudget.GetHash();

// create fee tx
CTransactionRef wtx;
CReserveKey keyChange(vpwallets[0]);
if (!vpwallets[0]->CreateBudgetFeeTX(wtx, budgetHash, keyChange, true)) {
throw std::runtime_error("Can't make collateral transaction");
}
// Send the tx to the network
const CWallet::CommitResult& res = vpwallets[0]->CommitTransaction(wtx, keyChange, g_connman.get());
UniValue ret(UniValue::VOBJ);
if (res.status == CWallet::CommitStatus::OK) {
ret.pushKV("result", "tx_fee_sent");
ret.pushKV("id", wtx->GetHash().ToString());
} else {
ret.pushKV("result", "error");
}
return ret;
}

UniValue ret(UniValue::VOBJ);
// Collateral tx already exists, see if it's mature enough.
CFinalizedBudget fb(budName, nBlockStart, vecTxBudgetPayments, *txFeeId);
if (g_budgetman.AddFinalizedBudget(fb)) {
fb.Relay();
ret.pushKV("result", "fin_budget_sent");
ret.pushKV("id", fb.GetHash().ToString());
} else {
// future: add proper error
ret.pushKV("result", "error");
}
return ret;
}

UniValue mnfinalbudget(const JSONRPCRequest& request)
{
std::string strCommand;
Expand Down Expand Up @@ -879,6 +966,7 @@ static const CRPCCommand commands[] =

/* Not shown in help */
{ "hidden", "mnfinalbudgetsuggest", &mnfinalbudgetsuggest, true, {} },
{ "hidden", "createrawmnfinalbudget", &createrawmnfinalbudget, true, {"budgetname", "blockstart", "proposals", "feetxid"} },

};

Expand Down
2 changes: 2 additions & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ static const CRPCConvertParam vRPCConvertParams[] = {
{ "createrawtransaction", 0, "inputs" },
{ "createrawtransaction", 1, "outputs" },
{ "createrawtransaction", 2, "locktime" },
{"createrawmnfinalbudget", 1, "blockstart"},
{"createrawmnfinalbudget", 2, "proposals"},
{ "delegatestake", 1, "amount" },
{ "delegatestake", 3, "ext_owner" },
{ "delegatestake", 4, "include_delegated" },
Expand Down
Loading