Package transactions submitted to the submitpackage RPC successfully are accepted to the node’s mempool, but broadcasted to peers individually because package relay is currently a work in progress. Successful submission does not mean the transactions will propagate.
maxburnamount is an optional parameter for the sendrawtransaction RPC that helps prevent users from accidentally burning funds. Transactions with a data carrier OP_RETURN output amount that exceeds maxburnamount (default value: 0) are not submitted or broadcasted.
Upon decoding a transaction in sendrawtransaction and testmempoolaccept RPCs, maxburnamount is checked immediately.
maxfeerate is an optional parameter for the sendrawtransaction and testmempoolaccept RPCs. Transactions exceeding this feerate won’t be added to mempool and broadcasted to peers, helping prevent unintentional overpayment.
testmempoolaccept performs maxfeerate check after package processing. For each successful transaction, it uses the base fee and transaction virtual size in the validation result to check that the feerate does not exceedmaxfeerate.
In the sendrawtransaction RPC, maxfeerate check is performed by calculating the transaction size fee at maxfeerate fee rate (as max_raw_tx_fee) and passing it to BroadcastTransaction. BroadcastTransaction first does a test accept in order to get the fee and virtual size of the transaction. Transactions whose feerate does not exceed the max_raw_tx_fee are then submitted to the mempool and broadcasted if successful.
This PR adds optional parameters maxfeerate and maxburnamount to the submitpackage RPC, enabling similar checks on package transactions.
Why is it important to perform these checks on submitted packages?
Are there other important checks apart from maxburnamount and maxfeerate that should be performed on packages before they are accepted to the mempool?
The options maxburnamount and maxfeerate can prevent a transaction from entering the mempool and being relayed. Can we consider these options as policy rules? Why or why not?
The commit message states: “This allows subpackage processing and is compatible with future package RBF work.” What makes this compatible with future RBF work?
Why do we validate maxfeerate against the modified feerate instead of the base fee rate?
We validate maxfeerate against the modified feerate of individual package transactions, not package feerate.
When can this be inaccurate?
Why not use package feerate instead?
Under what conditions might it become problematic?
Why can’t maxfeerate be checked immediately after decoding like maxburnamount is?
How does the maxfeerate check in testmempoolaccept RPC differ from submitpackage RPC? Why can’t they be the same?
Can you think of a different approach from the one taken by this PR? What are the tradeoffs?
<abubakarsadiq> Hello everyone today we are looking at PR #28950 authored by instagibbs, notes and question are available here https://bitcoincore.reviews/28950
<larryruane_> is it just that if there's a reason to have a check on a single tx submission, then that check would also make sense for the txes within a package?
<abubakarsadiq> yes @monlovesmango @larryruane it will be helpful to users in ensuring the transactions in packages they are adding to their mempool and broadcasting to peers does not pay unreasonable fee rate
<abubakarsadiq> 2.Are there other important checks apart from maxburnamount and maxfeerate that should be performed on packages before they are accepted to the mempool?
<abubakarsadiq> maybe we can also can also check package transactions does not exceed the maximum standard transaction size and fail early. However I don't think users should configure this?
<abubakarsadiq> 3. The options `maxburnamount` and `maxfeerate` can prevent a transaction from entering the mempool and being relayed. Can we consider these options as policy rules? Why or why not?
<abubakarsadiq> 4. The commit message states: “This allows subpackage processing and is compatible with future package RBF work.” What makes this compatible with future RBF work?
<abubakarsadiq> Is it because subpackage processing is where package RBF rules will be checked, and we check the individual modified fee rate against `maxfeerate` during subpackage evaluation/
<monlovesmango> so is "This allows subpackage processing WHICH is compatible with future package RBF work." more apt for the description of the commit?
<abubakarsadiq> I not sure why also It's a bit unclear to me that `sendrawtransaction` and `testmempoolaccept` `maxfeerate` checks are validated against base fee while `submitpackage` is using a modified fee rate.
<larryruane_> glozow: I think I see what you mean; the maxfeerate is a local parameter so the user can adjust that param directly (user would know the modified feerate)
<instagibbs> I don't know, with non-trivial structures I think that will be difficult. modified feerate is what drives subpackage eval, and would drive linearization post-cluster mempool?
<instagibbs> glozow it definitely will change it, but if you think modified is the wrong thing, then maybe the future approach would ahve been wrong too
<monlovesmango> abubakarsadiq: would it be inaccurate if we bump the fee to be higher than 'maxfeerate' and then subsequently bump the package fee to be lower than 'maxfeerate'?
<abubakarsadiq> even if prioritization affect linearization, I think the aim is to check the actual fee rate, should do just because thats what other nodes will see when its broadcasted?
<abubakarsadiq> @monlovesmango: I think its when the package child transaction is rejected because its modified fee rate exceeds `maxfeerate` individually, but does not if it's checked as a package.
<vmammal> i feel like maxfeerate check should occur on a package, if possible. it seems the answer given on the PR is that this check occurs "prior to any relay"
<abubakarsadiq> I dont think it would be possible with the current approach because the transaction fee and size are determined during subpackage processing, we have to just check at that time, the subpackage will be added to the mempool (if it passed the check) before the next subpackage is going to be evaluated.
<glozow> we know the aggregate package feerate, but it's not an accurate assessment. Let's say you have parents A and B, and child C. parent B spends parent A.
<glozow> No - so imagine that A+B are large and together not above the maxfeerate, but C is. C should fail the maxfeerate check, but wouldn't because its fees are absorbed by A+B in the aggregation
<abubakarsadiq> @monlovesmango because B CPFP A, and C is an individual txs. so should instead check against (A,B) and then check against (C) seperately.
<abubakarsadiq> Welcome everyone, lets continue the discussion of PR #28950 by @instagibbs yesterday discussion are available already on https://bitcoincore.reviews/28950
<abubakarsadiq> since now we just check against individual transaction if it were possible we should just do the check after decoding all the package transactions
<abubakarsadiq> but thats not possible because the fee and size are known during package processing after we load coins and subtract output values from input values
<abubakarsadiq> It’s done after the testaccept package processing because the txs are not added to mempool and broadcasted after the processing, we can safely check maxfeerate and return appropriate error messages.
<abubakarsadiq> They cannot be the same because in `submitpackage`, the package transactions might have already been accepted into the mempool and broadcasted to peers, rendering the check redundant.
<abubakarsadiq> Do you mean why we check `maxfeerate` after the package has been processed? Thats because the package processing only `test_accept`, i.e see if we can accept this list of transactions, they are not actually accepted.
<monlovesmango> yes thats what I meant. why can't `testmempoolaccept` use modified fee rate? if testing acceptance into mempool seems like you want to use modified fee rate?
<abubakarsadiq> 2. Adding a helper that loads coins and calculate a fees, and calculate vsize so that we can immediately perform the check before package processing.
<monlovesmango> I assume theres also some duplicative processing? since earlier it was said that you need to process the package to figure out fee rate
<monlovesmango> is trade off for 2 similar to 1? I guess I don't understand enough to really differentiate between 1 and 2, since both perform maxfeerate check prior to package processing
<vmammal> in `test/functional/rpc_packages.py`, under "relax restrictions.. parent gets through", I was wondering what happened to the child tx. But I think I answered my own question - the child IsUnspendable?
<abubakarsadiq> So If i understand this correctly the tradeoff is that in the future when we have cluster mempool we will like to check `maxfeerate` against chunk fee rate not individual fee rate.
<abubakarsadiq> The approach is suggesting we create a helper function that calculate the fee rate of all the package transactions and their sizes and we `maxfeerate` against individual txs fee rate early before package processing.
<abubakarsadiq> But when we have cluster mempool, we would like to switch to checking `maxfeerate` against the chunk fee rate, which means this approach is not extensible to that, we have to update and check after the package is linearized and we got the chunk fee rate.