Skip to content

Conversation

glozow
Copy link
Member

@glozow glozow commented Mar 11, 2022

Came up while reviewing #24364, where some of us incorrectly assumed that we use the same fee deduction in CTxMemPoolModifiedEntry::nModFeesWithAncestors when first constructing an entry and in update_for_parent_inclusion.

Actually, the behavior is this: when a mempool entry's ancestor is included in the block template, we create a CTxMemPoolModifiedEntry for it, subtracting the ancestor's modified fees from nModFeesWithAncestors. If another ancestor is included, we update it again, but use the ancestor's base fees instead.

I can't explain why we use GetFee in one place and GetModifiedFee in the other, but I'm quite certain we should be using the same one for both.

And should it be base or modified fees? Modified, otherwise the child inherits the prioritisation of the parent, but only until the parent gets mined. If we want prioritisation to cascade down to current in-mempool descendants, we should probably document that in the prioritsetransaction helpstring and implement it in CTxMemPool::mapDeltas, not as a quirk in the mining code?

Wrote a test in which a mempool entry has 2 ancestors, both prioritised, and both included in a block template individually. This test should fail without the s/GetFee/GetModifiedFee commit.

@glozow glozow added the Mining label Mar 11, 2022
@glozow
Copy link
Member Author

glozow commented Mar 11, 2022

cc @jamesob

@@ -116,7 +116,7 @@ struct update_for_parent_inclusion

void operator() (CTxMemPoolModifiedEntry &e)
{
e.nModFeesWithAncestors -= iter->GetFee();
e.nModFeesWithAncestors -= iter->GetModifiedFee();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. Good catch!

@maflcko
Copy link
Member

maflcko commented Mar 11, 2022

Concept ACK

@DrahtBot
Copy link
Contributor

DrahtBot commented Mar 12, 2022

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #24595 (deploymentstatus: move g_versionbitscache global to ChainstateManager by ajtowns)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@glozow glozow force-pushed the 2022-03-miner-prioritised branch from fc292c4 to e4303c3 Compare March 14, 2022 16:04
@glozow
Copy link
Member Author

glozow commented Mar 14, 2022

Rebased for #24080.

@theStack
Copy link
Contributor

Concept ACK

@ccdle12
Copy link
Contributor

ccdle12 commented Apr 25, 2022

tested ACK e4303c3

and I guess concept ACK as well, since it seems undesirable for a miner to think they are prioritizing a single tx but actually has after effects on other txs (descendants) in terms of selection

@maflcko
Copy link
Member

maflcko commented May 6, 2022

LGTM. I also checked that without the fix, CNB will incorrectly include the 0-fee, non-prioritized child:

diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 7e26e732f5..fa67ddb419 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -530,15 +530,15 @@ void MinerTestingSetup::TestPrioritisedMining(const CChainParams& chainparams, c
     m_node.mempool->addUnchecked(entry.Fee(0).SpendsCoinbase(false).FromTx(tx));
 
     auto pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
-    BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 6U);
+    BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 7U);
     BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashFreeParent);
     BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashFreePrioritisedTx);
     BOOST_CHECK(pblocktemplate->block.vtx[3]->GetHash() == hashParentTx);
     BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashPrioritsedChild);
     BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashFreeChild);
+        // The FreeParent and FreeChild's prioritisations *does* impact the child.
+        BOOST_CHECK(pblocktemplate->block.vtx[6]->GetHash() == hashFreeGrandchild);
     for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
-        // The FreeParent and FreeChild's prioritisations should not impact the child.
-        BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeGrandchild);
         // De-prioritised transaction should not be included.
         BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashMediumFeeTx);
     }

@maflcko
Copy link
Member

maflcko commented May 6, 2022

ACK e4303c3 🚗

Show signature

Signature:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

ACK e4303c337c8423f21c2c72ee1bcca3aaf46fa1cb 🚗
-----BEGIN PGP SIGNATURE-----

iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
pUhmJAwAuY9dx5XOXwABGKOcz5KDvk2LekoeYMJgUe9H0Lql2sEi/BcZcU95c3HN
f3yRTEHWneiqhUz4jNcks+wXTM2e93wSTGZc0AxF20B2VUlnks1MD5EC1MQK2Bzc
Ip+yh43QZck21xoyyyOnBjiVO0gk8a+AAjSxHRmGB5rni2dEhSFX/nZef9fEGZq2
Cjp65fd8V6JOHiMIdHrscp228jm5K8Dsa/c6ucqGZuab8kl9vFj/GpV4FrisIlFo
7t6fJv9fSb6MWILwr3C7Hu8hDZr2Dhd13O1T2afhoBxD9W2sfLQcmtTuQvjZl5qt
St5PtWeztYcaMKWUlBcFHjsbdatTFYosA2qFiCHRUPGwf/UBeEGZlz0XlqvzRD9X
nMj+/oSGKSStTSszhIyIk7DHb4ZhRmKkq7n32GBSZq4qGXmmfy8S00LwQO1I8OOK
PhISXSJ3aj0O4w7KrgmrwrnP8do257J4NCk1v9NHFtEmxBN8p96t1rPqYg+bBwdm
xhL7ZPDe
=zM+y
-----END PGP SIGNATURE-----

@maflcko maflcko merged commit b2e7811 into bitcoin:master May 6, 2022
@glozow glozow deleted the 2022-03-miner-prioritised branch May 8, 2022 19:33
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request May 9, 2022
…ing modified fees, not base

e4303c3 [unit test] prioritisation in mining (glozow)
7a8d606 [miner] bug fix: update for parent inclusion using modified fee (glozow)
0f9a444 MOVEONLY: group miner tests into MinerTestingSetup functions (glozow)

Pull request description:

  Came up while reviewing bitcoin#24364, where some of us incorrectly assumed that we use the same fee deduction in `CTxMemPoolModifiedEntry::nModFeesWithAncestors` when first constructing an entry and in `update_for_parent_inclusion`.

  Actually, the behavior is this: when a mempool entry's ancestor is included in the block template, we create a `CTxMemPoolModifiedEntry` for it, subtracting the ancestor's modified fees from `nModFeesWithAncestors`. If another ancestor is included, we update it again, but use the ancestor's _base_ fees instead.

  I can't explain why we use `GetFee` in one place and `GetModifiedFee` in the other, but I'm quite certain we should be using the same one for both.

  And should it be base or modified fees? Modified, otherwise the child inherits the prioritisation of the parent, but only until the parent gets mined. If we want prioritisation to cascade down to current in-mempool descendants, we should probably document that in the `prioritsetransaction` helpstring and implement it in `CTxMemPool::mapDeltas`, not as a quirk in the mining code?

  Wrote a test in which a mempool entry has 2 ancestors, both prioritised, and both included in a block template individually. This test should fail without the s/GetFee/GetModifiedFee commit.

ACKs for top commit:
  ccdle12:
    tested ACK e4303c3
  MarcoFalke:
    ACK e4303c3 🚗

Tree-SHA512: 4cd94106fbc9353e9f9b6d5af268ecda5aec7539245298c940ca220606dd0737264505bfaae1f83d94765cc2d9e1a6e913a765048fe6c19292482241761a6762
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Jan 6, 2023
…t base

Summary:
```
Came up while reviewing #24364, where some of us incorrectly assumed that we use the same fee deduction in CTxMemPoolModifiedEntry::nModFeesWithAncestors when first constructing an entry and in update_for_parent_inclusion.

Actually, the behavior is this: when a mempool entry's ancestor is included in the block template, we create a CTxMemPoolModifiedEntry for it, subtracting the ancestor's modified fees from nModFeesWithAncestors. If another ancestor is included, we update it again, but use the ancestor's base fees instead.

I can't explain why we use GetFee in one place and GetModifiedFee in the other, but I'm quite certain we should be using the same one for both.

And should it be base or modified fees? Modified, otherwise the child inherits the prioritisation of the parent, but only until the parent gets mined. If we want prioritisation to cascade down to current in-mempool descendants, we should probably document that in the prioritsetransaction helpstring and implement it in CTxMemPool::mapDeltas, not as a quirk in the mining code?

Wrote a test in which a mempool entry has 2 ancestors, both prioritised, and both included in a block template individually. This test should fail without the s/GetFee/GetModifiedFee commit.
```

Backport of [[bitcoin/bitcoin#24538 | core#24538]].

Depends on D12951.

Test Plan:
  ninja check-all

Reviewers: #bitcoin_abc, sdulfari

Reviewed By: #bitcoin_abc, sdulfari

Subscribers: sdulfari

Differential Revision: https://reviews.bitcoinabc.org/D12953
@bitcoin bitcoin locked and limited conversation to collaborators May 8, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants