test: Add functional test for replacement relay fee check #22310
Conversation
There was a problem hiding this comment.
any reason to change the reject string? This will just cause a headache for downstream project (if they use the reject string) and might even be controversial due to the change "fee" -> "penalty".
There was a problem hiding this comment.
Also the commit title is wrong? Mentions rule 5, but this is rule 4?
There was a problem hiding this comment.
Pushed new commit, updating to rule 4.
W.r.t to headache for downstream project, it's motivated by the fact that this same reject reason is already used L897 for the "higher fee" check and L833 for the "higher feerate" check.
Do we want to dissipate the confusion ? I would say it's better but can just drop it if you think it's too bothering for downstream.
There was a problem hiding this comment.
If you really want to change it, a separate pull request with clear rationale to motivate the change (and the hassle it causes) would be better. Bundling it with a change that is adding a test might not be the best approach.
There was a problem hiding this comment.
Obviously it needs release notes etc. Though, I'd rather avoid breaking downstream via reject reasons, which might break silently because they are not an enum. #19339 (comment)
There was a problem hiding this comment.
Ah okay, well I'll let the confusion for now and just happy to have test coverage. Updated the branch.
d19c7cc to
cdb84f1
Compare
8854ad6 to
8014964
Compare
There was a problem hiding this comment.
how is this test different from the one above? # Should fail because we haven't changed the fee
There was a problem hiding this comment.
It is different because the newly added test adds coverage for previously uncovered code https://marcofalke.github.io/btc_cov/total.coverage/src/validation.cpp.gcov.html
There was a problem hiding this comment.
The fee and fee per KB are lower though?
There was a problem hiding this comment.
I think the replacement_transaction output value is CTxOut(int(1 * COIN - 1)) so it has a higher fee/fee per KB, as everything else is constant.
You can verify with the following diff :
@@ -892,6 +894,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// The replacement must pay greater fees than the transactions it
// replaces - if we did the bandwidth used by those conflicting
// transactions would not be paid for.
+ LogPrintf("nModifiedFees %d\n", nModifiedFees);
+ LogPrintf("nConflictingFees %d\n", nConflictingFees);
if (nModifiedFees < nConflictingFees)
{
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee",
|
Nice catch. Concept ACK |
There was a problem hiding this comment.
any reason to not use miniwallet, like in the previous test?
There was a problem hiding this comment.
Well I think it makes the test a bit longer because it doesn't give you an outpoint but an utxo ? Though I took it anyway.
There was a problem hiding this comment.
heh, the point is to create the tx with the miniwallet. In that case the test should be three lines or so.
There was a problem hiding this comment.
Okay I did drop the miniwallet usage as AFAICT its fee_rate argument doesn't allow the feerate granularity (sat per KvB) required to hit the yet-uncovered branch ? Or at least without modifying node's default incrementalrelayfee
8014964 to
4bcb8d1
Compare
There was a problem hiding this comment.
So now this is the very same test as in test_simple_doublespend:
bitcoin/test/functional/feature_rbf.py
Lines 133 to 148 in 7317e14
I think (untested) it would be caught in:
Lines 830 to 838 in 7317e14
Which is already a covered branch.
You need to keep the lower higher feerate to get to the yet-uncovered branch of:
Lines 892 to 900 in 7317e14
And if you modified that because of my previous brainfart i'm sorry 😶
There was a problem hiding this comment.
You need to keep the lower feerate to get to the yet-uncovered branch of:
Oh yes effectively, do you mean the higher feerate ?
At 58cdabe6, feerates are the following:
node0 2021-06-24T15:51:23.735515Z [httpworker.0] [validation.cpp:831] [PreChecks] newFeeRate 583.33333345 BTC/kvB
node0 2021-06-24T15:51:23.735525Z [httpworker.0] [validation.cpp:832] [PreChecks] oldFeeRate 583.33333333 BTC/kvB
I think it's a +1 to have different reject_reason :p
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsNo conflicts as of last run. |
4bcb8d1 to
58cdabe
Compare
maflcko
left a comment
There was a problem hiding this comment.
Left a review comment about a comment.
Also, would be good to use MiniWallet, to that the test doesn't have to be touched again in the future when someone wants to run policy tests without the wallet. (Lightning doesn't run on the Bitcoin Core wallet, so I presume the wallet will generally be disabled)
There was a problem hiding this comment.
Is is "equal fee" if the fee is increased?
Again, I'd recommend to use MiniWallet, which will simplify this test a lot:
def test_replacement_relay_fee(self):
wallet = MiniWallet(self.nodes[0])
wallet.scan_blocks(start=77, num=1)
tx = wallet.send_self_transfer(from_node=self.nodes[0])['tx']
tx.vout[0].nValue -= 1
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx.serialize().hex())There was a problem hiding this comment.
Ooops, leftover from the multiple updates of this PR with the converation here.
58cdabe to
c4ddee6
Compare
|
@MarcoFalke, Fair point, updated at c4ddee6 with MiniWallet and hopefully binding comment, thanks for the code snippet! IMHO, I prefer to use the low-level test framework API to illustrate etchy, confusing case of our mempool logic but I understand for maintainability the usage of the higher API is better. Note to reviewers, hopefully the following diff should let you exercise the new test coverage, without blurring with other related "insufficient fee" checks: |
|
|
||
| # Higher fee, higher feerate, different txid, but the replacement does not provide a relay | ||
| # fee conforming to node's `incrementalrelayfee` policy of 1000 sat per KB. | ||
| tx.vout[0].nValue -= 1 |
There was a problem hiding this comment.
(nit) was slightly surprised that 1 was parsed as 1 satoshi and that the tx didn't need a new signature
| tx.vout[0].nValue -= 1 | |
| # Increase the fee by 1 satoshi. Same signature works because it is an anyone-can-spend. | |
| tx.vout[0].nValue -= Decimal("0.00000001") |
There was a problem hiding this comment.
The test wouldn't pass with the suggestion applied
|
cr ACK c4ddee6 |
|
https://marcofalke.github.io/btc_cov/total.coverage/src/validation.cpp.gcov.html#907 should be green in about 24 hours |
…fee check c4ddee6 test: Add test for replacement relay fee check (Antoine Riard) Pull request description: This PR adds rename the `reject_reason` of our implementation of BIP125 rule 4 and adds missing functional test coverage. Note, `insufficient fee` is already the `reject_reason` of few others `PreChecks` replacement checks and as such might be confusing. > The replacement transaction must also pay for its own bandwidth at or above the rate set by the node's minimum relay fee setting. For example, if the minimum relay fee is 1 satoshi/byte and the replacement transaction is 500 bytes total, then the replacement must pay a fee at least 500 satoshis higher than the sum of the originals. ``` // Finally in addition to paying more fees than the conflicts the // new transaction must pay for its own bandwidth. CAmount nDeltaFees = nModifiedFees - nConflictingFees; if (nDeltaFees < ::incrementalRelayFee.GetFee(nSize)) { return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s", hash.ToString(), FormatMoney(nDeltaFees), FormatMoney(::incrementalRelayFee.GetFee(nSize)))); } ``` ACKs for top commit: MarcoFalke: cr ACK c4ddee6 glozow: ACK c4ddee6, one small suggestion if you retouch. Tree-SHA512: 7c5d1065db6e6fe57a9f083bf051a7a55eb9892de3a2888679d4a6853491608c93b6e35887ef383a9988d14713fa13a0b1d6134b7354af5fd54765f0d4e98568
This PR adds rename the
reject_reasonof our implementation of BIP125 rule 4 and adds missing functional test coverage. Note,insufficient feeis already thereject_reasonof few othersPreChecksreplacement checks and as such might be confusing.