-
Notifications
You must be signed in to change notification settings - Fork 38.7k
[WIP] [RPC] Add verifyrawtransaction RPC #11201
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
|
Well there is already a recommend way to do this: use a block proposal. The general limitation with a 'verifyrawtransaction' approach is that it doesn't let you test a graph of unconfirmed transactions, but a block proposal does. Looks like internally your rpc is doing more or less what a block proposal does, but handling more of the things around it. So perhaps it would be useful to do. It could obviously be extended to accept an array of transactions to do the right thing with respect to multiple... but another open question is what about parents in the mempool. Right now your code will fail a transaction that spends the output of a mempool transaction. Sometimes that would be desirable but I think often not. |
|
Seems awfully inefficient to call CNB just to throw away the chosen transaction-set. Also, the block fees will be wrong. If you don't want to build a block from scratch, maybe abstract that out of CNB first (separate commit, same PR)? (To revise your PR, just use |
|
Got it, thanks for the feedback. I'll address these issues now |
|
I agree with the general usefulness of a |
|
Concept ACK, but as others have said, there are other things to consider when verifying a transaction that are not done here. Those need to be documented. |
|
Seems related to #7552 |
|
Thanks much for that link @jtimon, somehow I missed that. It seems like everyone agrees that there is the potential for some useful functionality here, there's just some uncertainty in what exactly the API for this should look like. After reading #7552, it seems like this uncertainty is largely what has kept What if I think this achieves all of the behavior we want; users can set "use_local_policy" to false if they only want to check consensus rules. I will also make it handle ancestors in the mempool correctly as brought up by @gmaxwell, unless that should be another flag? I think I can do a lot of this with a minor refactor of Does this sound good? |
add tests fix typo add dryrun flag to AcceptToMemoryPool] check each transaction against local policy rules stop doing needless work in CreateNewBlock update docs add ancestor topological sort add better tests for multi ancestors and policy flag add moar tests make everything snake_case
|
As discussed on IRC, concept ACK. |
| } else if (missing_inputs) { | ||
| // We want to ignore the "missing inputs" case here, since the input | ||
| // may actually be in the mempool. If the input is truly missing, we | ||
| // will find out later after the ancestor and consensus check. |
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.
If ATMP fails for a transaction due to missing inputs, then almost none of the policy checks will be evaluated for the transaction, because that's one of the first things we (must) do -- for instance you can't check the feerate of the transaction without having the inputs available.
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.
Actually on further review, it looks like you've added these "dry run" transactions to the mempool, so now I think if ATMP returns "missing inputs", that should reflect an actual failure? Is there a case where that doesn't hold?
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.
Yeah -- this code is leftover from before I figured out the issue you mentioned in your first comment. I was working on getting rid of this when you left your review 😝
|
@justicz Thanks for working on this. I think there's still work to be done here, but this seems like a promising direction. Rather than add the If we can achieve that, that would make the review and maintenance burden of this feature pretty minimal, which I think would be awesome. |
| // Used by AcceptToMemoryPool(), which DOES do | ||
| // all the appropriate checks. | ||
| LOCK(cs); | ||
|
|
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.
The NotifyEntryAdded callback a few lines up shouldn't trigger for dry run transactions.
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.
👍
| if (plTxnReplaced) | ||
| plTxnReplaced->push_back(it->GetSharedTx()); | ||
| if (!fDryRun) { | ||
| // Remove conflicting transactions from the mempool |
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.
Since you only are removing conflicts in non-dryrun situations, doesn't that mean that someone calling verifyrawtransactions with a pair of tx's, one of which would replace existing transactions, and one of which depends on an existing transaction, would potentially succeed? Yet when actually trying to send, the second would necessarily fail.
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 think you're right. I'll fix this
|
Thanks for the comments @sdaftuar! I think I agree with all of the points you made and will work on separating things out of the mempool more cleanly. |
|
Hey @sdaftuar, it's not done yet (still need to implement eviction/properly count descendants) but I've been working on implementing the feature in the way you described over here: https://github.com/justicz/bitcoin/pull/3 . I broke the relevant parts of the CTxMemPool interface out into a CTxMemPoolBase class and then implemented a CTxMockMemPool that I pass into ATMP. Is this more what you had in mind? I'm modifying some of the const CTxMemPool methods to accept a cache so that I can avoid duplicating a lot of the logic. |
|
Closing this PR, will make a new one in the future if I can come up with an implementation I am happy with |
|
Please ping when you do come up with a better implementation. I have strong interest in this! |
Currently, there is not an RPC that allows for the validation of a raw transaction without actually submitting that transaction to the network. This PR implements
verifyrawtransaction, which accepts a hex encoded raw transaction and determines if it could be included in the next block. It does this by creating a "fake" block with the proposed transaction, and then checking that the block is valid withTestBlockValidity.This is my first attempt at contributing to bitcoin, so if I've already managed to break any unspoken (or spoken) rules, please let me know 😅