Skip to content

Commit

Permalink
Redo memory pool loop in MRCModel::refresh() and createmrcrewards
Browse files Browse the repository at this point in the history
  • Loading branch information
jamescowens committed May 13, 2022
1 parent bbc1005 commit 2e76211
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 29 deletions.
41 changes: 23 additions & 18 deletions src/qt/mrcmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,10 @@ void MRCModel::refresh() EXCLUSIVE_LOCKS_REQUIRED(cs_main)

bool found{false};

// This will allow sorting the fees in descending order to help determine the payout limit fee.
std::vector<CAmount> mrc_fee_vector;
// This sorts the MRCs in descending order of MRC fees to allow determination of the payout limit fee.

// ---------- mrc fee --- mrc ------ descending order
std::multimap<CAmount, GRC::MRC, std::greater<CAmount>> mrc_multimap;

for (const auto& [_, tx] : mempool.mapTx) {
if (!tx.GetContracts().empty()) {
Expand All @@ -267,34 +269,37 @@ void MRCModel::refresh() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
if (contract.m_type == GRC::ContractType::MRC) {
GRC::MRC mempool_mrc = contract.CopyPayloadAs<GRC::MRC>();

found |= m_mrc.m_mining_id == mempool_mrc.m_mining_id;
mrc_multimap.insert(std::make_pair(mempool_mrc.m_fee, mempool_mrc));
} // match to mrc contract type
} // contract present in transaction?
}

if (!found && mempool_mrc.m_fee >= m_mrc.m_fee) ++m_mrc_pos;
m_mrc_queue_head_fee = std::max(m_mrc_queue_head_fee, mempool_mrc.m_fee);
m_mrc_queue_tail_fee = std::min(m_mrc_queue_tail_fee, mempool_mrc.m_fee);
for (const auto& [_, mempool_mrc] : mrc_multimap) {
found |= m_mrc.m_mining_id == mempool_mrc.m_mining_id;

mrc_fee_vector.push_back(mempool_mrc.m_fee);
if (!found && mempool_mrc.m_fee >= m_mrc.m_fee) ++m_mrc_pos;
m_mrc_queue_head_fee = std::max(m_mrc_queue_head_fee, mempool_mrc.m_fee);
m_mrc_queue_tail_fee = std::min(m_mrc_queue_tail_fee, mempool_mrc.m_fee);

++m_mrc_queue_length;
} // match to mrc contract type
} // contract present in transaction?
} // mempool transaction iterator
++m_mrc_queue_length;
}

// The tail fee converges from the max numeric limit of CAmount; however, when the above loop is done
// it cannot end up with a number higher than the head fee. This can happen if there are no MRC transactions
// in the loop.
m_mrc_queue_tail_fee = std::min(m_mrc_queue_head_fee, m_mrc_queue_tail_fee);

// Sort the fees in descending order for the pay limit calculation.
std::sort(mrc_fee_vector.begin(), mrc_fee_vector.end(), std::greater<CAmount>());

// Here we select the minimum of the mrc_fee_vector.size() - 1 in the case where the sorted vector does not reach the
// m_mrc_output_limit - 1, or the m_mrc_output_limit - 1 if the sorted vector indicates the queue is (over)full,
// Here we select the minimum of the mrc_multimap.size() - 1 in the case where the multimap does not reach the
// m_mrc_output_limit - 1, or the m_mrc_output_limit - 1 if the multimap indicates the queue is (over)full,
// i.e. the number of MRC's in the queue exceeds the m_mrc_output_limit for paying in a block.
int pay_limit_fee_pos = std::min<int>(mrc_fee_vector.size(), m_mrc_output_limit) - 1;
int pay_limit_fee_pos = std::min<int>(mrc_multimap.size(), m_mrc_output_limit) - 1;

if (pay_limit_fee_pos >= 0) {
m_mrc_queue_pay_limit_fee = mrc_fee_vector[pay_limit_fee_pos];
std::multimap<CAmount, GRC::MRC, std::greater<CAmount>>::iterator iter = mrc_multimap.begin();

std::advance(iter, pay_limit_fee_pos);

m_mrc_queue_pay_limit_fee = iter->first;
}

m_mrc_queue_pay_limit_fee = std::min(m_mrc_queue_head_fee, m_mrc_queue_pay_limit_fee);
Expand Down
8 changes: 7 additions & 1 deletion src/qt/mrcrequestpage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,13 @@ void MRCRequestPage::updateMRCStatus()
ui->mrcQueueLimit->setText(QString::number(m_mrc_model->getMRCOutputLimit()));
ui->numMRCInQueue->setText(QString::number(m_mrc_model->getMRCQueueLength()));
ui->mrcQueueHeadFee->setText(BitcoinUnits::formatWithUnit(display_unit, m_mrc_model->getMRCQueueHeadFee()));
ui->mrcQueuePayLimitFee->setText(BitcoinUnits::formatWithUnit(display_unit, m_mrc_model->getMRCQueuePayLimitFee()));

if (m_mrc_model->getMRCQueueLength() >= m_mrc_model->getMRCOutputLimit()) {
ui->mrcQueuePayLimitFee->setText(BitcoinUnits::formatWithUnit(display_unit, m_mrc_model->getMRCQueuePayLimitFee()));
} else {
ui->mrcQueuePayLimitFee->setText("N/A");
}

ui->mrcQueueTailFee->setText(BitcoinUnits::formatWithUnit(display_unit, m_mrc_model->getMRCQueueTailFee()));

MRCRequestStatus s;
Expand Down
61 changes: 51 additions & 10 deletions src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2543,26 +2543,59 @@ UniValue createmrcrequest(const UniValue& params, const bool fHelp) {
int pos{0};
bool found{false};
CAmount tail_fee{std::numeric_limits<CAmount>::max()};
CAmount pay_limit_fee{std::numeric_limits<CAmount>::max()};
CAmount head_fee{0};
int queue_length{0};
int limit = static_cast<int>(GetMRCOutputLimit(pindex->nVersion, false));

// This sorts the MRCs in descending order of MRC fees to allow determination of the payout limit fee.

// ---------- mrc fee --- mrc ------ descending order
std::multimap<CAmount, GRC::MRC, std::greater<CAmount>> mrc_multimap;

for (const auto& [_, tx] : mempool.mapTx) {
for (const auto& contract: tx.GetContracts()) {
if (!tx.GetContracts().empty()) {
// By protocol the MRC contract MUST be the only one in the transaction.
const GRC::Contract& contract = tx.GetContracts()[0];

if (contract.m_type == GRC::ContractType::MRC) {
GRC::MRC mempool_mrc = contract.CopyPayloadAs<GRC::MRC>();

found |= mrc.m_mining_id == mempool_mrc.m_mining_id;
pos += mempool_mrc.m_fee >= mrc.m_fee;
head_fee = std::max(head_fee, mempool_mrc.m_fee);
tail_fee = std::min(tail_fee, mempool_mrc.m_fee);
mrc_multimap.insert(std::make_pair(mempool_mrc.m_fee, mempool_mrc));
} // match to mrc contract type
} // contract iterator
} // mempool transaction iterator
} // contract present in transaction?
}

for (const auto& [_, mempool_mrc] : mrc_multimap) {
found |= mrc.m_mining_id == mempool_mrc.m_mining_id;

if (!found && mempool_mrc.m_fee >= mrc.m_fee) ++pos;
head_fee = std::max(head_fee, mempool_mrc.m_fee);
tail_fee = std::min(tail_fee, mempool_mrc.m_fee);

++queue_length;
}

// The tail fee converges from the max numeric limit of CAmount; however, when the above loop is done
// it cannot end up with a number higher than the head fee. This can happen if there are no MRC transactions
// in the loop.
tail_fee = std::min(head_fee, tail_fee);

int limit = static_cast<int>(GetMRCOutputLimit(pindex->nVersion, false));
// Here we select the minimum of the mrc_multimap.size() - 1 in the case where the multimap does not reach the
// m_mrc_output_limit - 1, or the m_mrc_output_limit - 1 if the multimap indicates the queue is (over)full,
// i.e. the number of MRC's in the queue exceeds the m_mrc_output_limit for paying in a block.
int pay_limit_fee_pos = std::min<int>(mrc_multimap.size(), limit) - 1;

if (pay_limit_fee_pos >= 0) {
std::multimap<CAmount, GRC::MRC, std::greater<CAmount>>::iterator iter = mrc_multimap.begin();

std::advance(iter, pay_limit_fee_pos);

pay_limit_fee = iter->first;
}

pay_limit_fee = std::min(head_fee, pay_limit_fee);


if (!dry_run && !force) {
if (found) {
Expand All @@ -2576,11 +2609,19 @@ UniValue createmrcrequest(const UniValue& params, const bool fHelp) {

resp.pushKV("outstanding_request", found);
// Sadly, humans start indexing by 1.
resp.pushKV("pos", pos + 1);
resp.pushKV("limit", limit);
resp.pushKV("tail_fee", ValueFromAmount(tail_fee));
resp.pushKV("mrcs_in_queue", queue_length);
resp.pushKV("head_fee", ValueFromAmount(head_fee));

if (queue_length >= limit) {
resp.pushKV("pay_limit_position_fee", ValueFromAmount(pay_limit_fee));
} else {
resp.pushKV("pay_limit_position_fee", "N/A");
}

resp.pushKV("tail_fee", ValueFromAmount(tail_fee));
resp.pushKV("pos", pos + 1);

if (!dry_run) {
LOCK(pwalletMain->cs_wallet);

Expand Down

0 comments on commit 2e76211

Please sign in to comment.