-
Notifications
You must be signed in to change notification settings - Fork 291
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mempool/mining: Implement aggregate fee sorting. #1829
Conversation
Nice! This will obviously need a lot of review and testing, but the idea is sound and I'm happy to see work towards this. |
Hit a panic while testing this prior to review:
|
Tested this PR with dcrpool's mining harness, I'm yet to identify the root cause of the issue but I can't mine past SVH because tickets are not being bought. Switching to master fixes this issue, will take a closer look. |
c8c3948
to
85f17c6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Round 1 review. I still have quite a bit more to get through, but I figured I would get these published since they're pretty minor and you can make the changes quickly in the mean time.
Also, please rebase this to the latest master. I would like to test it against the latest code and it currently has merge conflicts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still need to do more reviewing/testing, but had some minor comments on the first read through.
This has been rebased onto master. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had a few more comments. Overall, I think the code updating the mining view looks pretty solid, nice work on that!
One thing to note is that I do find the logic of updating ancestorStats
a bit hard to follow due to the combination of 1) several different code paths either recalculating, incrementing, or decrementing the stats and 2) that the aggregation is happening in the context of recursive functions. It may be worth considering if there is a more straightforward way to do this, otherwise, I think adding in some additional tests around some of the other scenarios that aren't currently tested (had an inline comment for these) would be helpful.
On the mining side, I did some basic tests, but need to still test that further since its a bit harder to hit all of the edge cases since there are not really any unit tests in place for that currently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noticed a couple more things when reviewing the mining code. Still need to test more and try to hit all/most of the various scenarios in simnet (if you already have any instructions on how to manually setup/test some of this in simnet, that would be helpful).
Given the size of this PR and the difficulty of exercising the test cases around the paths around ancestor aggregation during template gen, I think trimming this PR back to an earlier point (last week) would be best at this point:
Plus
And the major changes to the template gen should get split out into another PR and addressed at a later time. Does this seem fair? I'm really not clear on what minimum functionality is or has been expected to get this PR merged since there's been little chatter on code that's sitting here for almost a year, until now. |
I'll be giving this a final review and doing some more testing later today, but based on the updates, my previous review, and the fact I have been running the code without issue (with template generation active so it is being exercised of course), I believe this is probably pretty close to ready to go in. To answer your question, the key points for me to merge this now are:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking really close to me as well. I'm going to finish testing on the mining side by later today.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested on both testnet
and simnet
, including with dependent transactions in the mempool, and things were working as expected. Had one additional clarification around the logic for max sigops per block, which seems off to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice job overall! Thanks for taking this on and producing good quality code with solid tests for the mempool implementation. This is a great addition. I spotted a few minor issues that I've identified inline. Once those are remedied (along with the few remaining other review comments, this will be good to merge.
I should note that there are some other nitpicks that I didn't call out such as that I think the graph implementation could be improved in terms of memory efficiency in a few spots and it ideally would avoid recursion in the depth-first logic, but those are not things this PR should be held up for since it is still quite reasonably efficient, works properly (outside of the aforementioned minor points), and has been heavily tested with the existing code (and suggested modifications plus sigop counting fix applied locally).
I added some timing prints and ran this on mainnet for a while to get a feel for the overall time it takes to build a template and, as can be seen, the times are quite reasonable. There is a lot of optimization work that can be done on the mining template code now that the mining
module is separate and internal and therefore can have proper tests added for it.
MINR: Time to create template: 995µs
MINR: Time to create template: 2.9956ms
MINR: Time to create template: 5.9869ms
MINR: Time to create template: 3.0019ms
MINR: Time to create template: 2.9986ms
MINR: Time to create template: 4.9793ms
MINR: Time to create template: 3.001ms
MINR: Time to create template: 4.0013ms
- Remove unused mining check since sigops combined into a single field. - Move mempool New() to end of file. - Update tests to expect actual sigops values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates. Review of updates inline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to do some final testing with the latest updates, but barring any issues in testing, this looks ready to me.
Also, just an FYI that I'm going to be squashing this down to a single commit when merging to get rid of all of the noise in the review updates. |
Looks like there is an issue with the ordering. I wrote a diff to make it easy to reproduce via simnet.
dcr_tmux_simnet_setup.sh diffdiff --git a/contrib/dcr_tmux_simnet_setup.sh b/contrib/dcr_tmux_simnet_setup.sh
index bdc463a5..6c95a5b2 100755
--- a/contrib/dcr_tmux_simnet_setup.sh
+++ b/contrib/dcr_tmux_simnet_setup.sh
@@ -58,8 +58,9 @@ rpcpass=${RPCPASS}
simnet=1
logdir=./log
datadir=./data
-debuglevel=TXMP=debug,MINR=debug
+debuglevel=TXMP=debug,MINR=trace
txindex=1
+blockprioritysize=0
EOF
cat > "${NODES_ROOT}/dcrctl.conf" <<EOF
@@ -176,6 +177,45 @@ fi
EOF
chmod +x "${NODES_ROOT}/${PRIMARY_WALLET_NAME}/xfer"
+cat > "${NODES_ROOT}/${PRIMARY_WALLET_NAME}/xferchain" <<EOF
+#!/usr/bin/env bash
+NUM=1
+case \$1 in
+ ''|*[!0-9]*) ;;
+ *) NUM=\$1 ;;
+esac
+
+utxos=\$(./ctl listunspent | jq "map(select(.spendable==true))")
+numutxos=\$(echo \$utxos | jq 'length')
+[[ \${numutxos} -ge 1 ]] || { echo "no unspent outputs"; exit 1; }
+
+utxo=\$(echo "\$utxos" | jq ".[0]")
+txid=\$(echo \$utxo | jq -r '.txid')
+vout=\$(echo \$utxo | jq -r '.vout')
+tree=\$(echo \$utxo | jq -r '.tree')
+amt=\$(echo \$utxo | jq -r '.amount')
+addr=\$(./ctl getnewaddress)
+basefee=2970
+for i in \$(seq 1 1 \${NUM}); do
+ fee=\$((\${basefee} * \${i}))
+ sendamt=\$(jq -rn "\${amt}-(\${fee}/1e8)")
+ newtxid=\$(./ctl createrawtransaction "[{\"amount\":\${amt},\"txid\":\"\${txid}\",\"vout\":\${vout},\"tree\":\${tree}}]" \
+ "{\"\${addr}\":\${sendamt}}" | \
+ ./ctl signrawtransaction - | jq -r .hex | \
+ ./ctl sendrawtransaction -)
+
+ echo "\${newtxid} (fee: \${fee}, spends from \${txid})"
+ txid=\${newtxid}
+ amt=\${sendamt}
+ vout=0
+ tree=0
+done
+cd ../dcrd1
+./ctl regentemplate
+EOF
+chmod +x "${NODES_ROOT}/${PRIMARY_WALLET_NAME}/xferchain"
+
+
sleep 1
tmux send-keys "./ctl importprivkey ${TSPEND_PRIMARY_WIF} imported false; ./ctl importprivkey ${TSPEND_SECONDARY_WIF} imported false" C-m
|
Thank you, this is fixed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed the latest updates and confirmed all remaining known issues are resolved. I ran a full set of tests with transactions spending from each other in various ways and manually examining the block templates for correctness.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good with the latest updates. Great work on this!
@sefbkn Would you please update the PR description to match reality? I was working to squash it all down and noticed the description is no longer entirely accurate. |
Relates to #1556
This pull request modified the mining prioritization logic to sort transactions by an aggregate fee based on a transaction’s ancestors in the mempool.
Currently, the mining code prioritizes transactions by fee and only includes them in the block template if they have no dependencies. When a transaction is included in the block template, it is removed as a dependency from transactions that depend on it, making those dependent transactions eligible for block template inclusion.
Aggregating ancestor statistics for large graphs of transactions in the mempool may have high computational costs. Performing this aggregation in the block template generator would delay miners requesting a block template since all of the aggregation would need to occur for each transaction, at once. To solve this problem, the complexity is spread over time such that the transaction statistics are updated with mempool event hooks. Since the mempool is not locked during the entirety of template generation, a mining view interface is exposed to safely interact with a snapshot of the mempool.
The biggest risk in terms of performance are reorgs where transactions with many descendants are added back to the mempool. The number of transactions added to the mempool in this way is limited by the block size and proof of work, but the mempool has no restrictions on the number of ancestors tracked for a given transaction.
A potential - and not implemented - solution to this reorg problem would be to establish a limit on the number of ancestors a transaction may have in the mempool.