-
Notifications
You must be signed in to change notification settings - Fork 38.6k
test: add BIP-125 rule 5 testcase with default mempool #25228
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
Conversation
And some little type annotation additions.
406e8de to
9b825e7
Compare
glozow
left a comment
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.
strong Concept ACK as we don't currently have test coverage for Rule 5 with default mempool limits
|
Concept ACK |
brunoerg
left a comment
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.
Concept ACK
9b825e7 to
fd564f3
Compare
|
Concept ACK |
|
Concept ACK. What do you think about also removing the test that uses the non-standard mempool config? |
danielabrozzoni
left a comment
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.
Concept ACK
This testcase exercises rule 5 of BIP-125 (no more than 100 evictions due to replacement) without having to test under non-default mempool parametmers.
fd564f3 to
687adda
Compare
Personally I don't think it hurts to have the coverage - the test seems to run pretty fast - but I did think it'd be interesting to add another test case with default params that uses a different (simpler) topology, which could just be uniting >125 individual txns. Edit: but IMO might as well just merge this and get the coverage, then think about adding more cases later. |
LarryRuane
left a comment
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.
ACK 687adda
I really like this new test, comments are just suggestions
| return self._address | ||
|
|
||
| def get_utxo(self, *, txid: str = '', vout: Optional[int] = None, mark_as_spent=True): | ||
| def get_utxo(self, *, txid: str = '', vout: Optional[int] = None, mark_as_spent=True) -> dict: |
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 PR doesn't seem to require this change, does it? If not, could you mention that in the commit message? That would help reviewers.
| def create_self_transfer_multi(self, *, from_node, utxos_to_spend=None, num_outputs=1, fee_per_output=1000): | ||
| def create_self_transfer_multi( | ||
| self, *, from_node, | ||
| utxos_to_spend: Optional[List[dict]] = None, |
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.
Same comment, this doesn't seem required; could you mention that in the commit comment?
| # For each root UTXO, create a package that contains the spend of that | ||
| # UTXO and `txs_per_graph` children tx. | ||
| for graph_num in range(num_tx_graphs): | ||
| root_utxos.append(wallet.get_utxo()) |
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.
| root_utxos.append(wallet.get_utxo()) | |
| utxo_parent_spend = wallet.get_utxo() | |
| root_utxos.append(utxo_parent_spend) |
so that code below is simpler
| optin_parent_tx = wallet.send_self_transfer_multi( | ||
| from_node=normal_node, | ||
| sequence=BIP125_SEQUENCE_NUMBER, | ||
| utxos_to_spend=[root_utxos[graph_num]], |
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.
| utxos_to_spend=[root_utxos[graph_num]], | |
| utxos_to_spend=[utxo_parent_spend], |
nit, slight readability improvement; I had to stare at the original for a while, the nested braces made me think at first it was some kind of double-nested index lookup! (Maybe it's just me.)
|
|
||
| assert normal_node.getmempoolentry(child_tx['txid']) | ||
|
|
||
| num_txs_invalidated = len(root_utxos) + (num_tx_graphs * txs_per_graph) |
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.
| num_txs_invalidated = len(root_utxos) + (num_tx_graphs * txs_per_graph) | |
| num_txs_to_invalidate = len(root_utxos) + (num_tx_graphs * txs_per_graph) |
nit variable rename, they're not invalided yet
| assert num_txs_invalidated > MAX_REPLACEMENT_LIMIT | ||
| else: | ||
| assert num_txs_invalidated <= MAX_REPLACEMENT_LIMIT | ||
|
|
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.
maybe add here (but requires a change below):
assert_equal(num_txs_to_invalidate, normal_node.getmempoolinfo()['size'])
| txid = normal_node.sendrawtransaction(tx_hex, 0) | ||
| assert normal_node.getmempoolentry(txid) |
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.
| txid = normal_node.sendrawtransaction(tx_hex, 0) | |
| assert normal_node.getmempoolentry(txid) | |
| # The replacement tx should have been accepted into the mempool and it | |
| # should be the only tx in the mempool (having replaced all others). | |
| txid = normal_node.sendrawtransaction(tx_hex, 0) | |
| assert normal_node.getmempoolentry(txid) | |
| assert_equal(normal_node.getmempoolinfo()['size'], 1) |
nit, just to clarify what is going on (would have helped me review), however the new assertion requires a change below.
| # Clear the mempool once finished, and rescan the other nodes' wallet | ||
| # to account for the spends we've made on `normal_node`. | ||
| self.generate(normal_node, 1) | ||
| self.wallet.rescan_utxos() |
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.
Indent these lines so the mempool gets cleared out at the end of each test case. Needed only if the assertions I recommended above are taken.
|
I am done making relatively minor changes to this PR. If there are problems with the correctness of the test I will fix them, but otherwise I have other things to do. |
|
Code review ACK 687adda
Fair enough, opening a PR doesn't oblige you to incorporate every minor suggestion, i think it's fine like this |
| self, *, from_node, | ||
| utxos_to_spend: Optional[List[dict]] = None, | ||
| num_outputs=1, | ||
| sequence=0, |
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.
Shouldn't this be an array of the same length as utxos_to_spend?
(Might fix in a follow-up)
Currently, we only test rule 5 of BIP-125 (replacement transactions cannot evict more than 100 transactions) by changing default mempool parameters to allow for more descendants. The current test works on a single transaction graph that has over 100 descendants.
This patch adds a test to exercise rule 5 using the default mempool parameters. The case is a little more sophisticated: instead of working on a single transaction graph, it uses a replacement transaction to "unite" several UTXOs which join independent transaction graphs. The total number of transactions in these graphs sum to more than the max allowable replacement.
I think the difference in transaction topology makes this a worthwhile testcase to have, setting aside the fact that this testcase works without having to use atypical mempool params.
See also: relevant discussion from IRC