blockchain: Test invalid ticket submission input. - #3800
Conversation
There was a problem hiding this comment.
Thanks for working through all of these cases.
It's not something to worry about for this PR (or this series you've been working on), but I would point out that since several of these are really only targeting CheckTransactionInputs they are doing a whole lot more work than is strictly necessary. They're creating a full chain with ~150 fully solved blocks (e.g. g.AdvanceToStakeValidationHeight, etc). Those in turn create an on-disk database for the blocks, utxoset, etc.
I understand why, because the chain generator has a lot of really nice infrastructure in place which greatly simplifies the testing by handling a lot of the minutia, so I'm not against it by any means.
I'm primarily mentioning it so that once you get done with the rest of the cases you're working on, if you're willing to take a stab it, something I think would be valuable is to implement something similar to a TestCheckTransactionInputs which would allow directly targeting every branch in the function. It is a free-standing function that doesn't require a full or synthetic chain or a functional ticket database. All it primarily needs, aside from the transaction being tested and agenda flags, is a SubsidyCache, a UtxoViewpoint, and a fake previous block header, all of which are independent entities that don't need a ton of interdependent setup.
Those tests could still potentially make use of Generator.CreateRevocationTx, Generator.CreateVoteTx, etc, though I'm not 100% on that point. They might need to be refactored to free-standing funcs that take more parameters which the generator methods call with the right params in order to support that.
With that in place, several of these types of tests would be significantly faster to run via that path.
This adds a test which ensures that the transaction input checks reject a vote or a revocation whose ticket input references an unspent stake output that is not part of a ticket purchase and accept them when the ticket input references a ticket purchase. The block validation path cannot trigger the rejection. The ticket redeemer checks run first and only allow votes for winning tickets and revocations for missed or expired tickets, and the ticket input must reference the first output, so it always references the first output of a ticket purchase. The mempool does not run the ticket redeemer checks, so it relies on the transaction input checks directly. The test calls the same function with the next block height a mempool caller would use. The rejected cases reference the first output of a revocation since it is an unspent stake output that is not part of a ticket purchase, whereas the first output of a vote is an OP_RETURN output that is never part of the utxo set.
8a7337f to
6138f93
Compare
|
Also yes, great idea. I'm definitely interested in working on that! |
This is work towards #1182.
This adds test coverage for the
checkTicketSubmissionInputsite ofErrInvalidVoteInput(previously namedErrInvalidSSGenInputbefore #1468) andErrInvalidRevokeInput(previously namedErrInvalidSSRtxInputbefore #1468).The old comments used to say:
Each error kind has two sites. The first rejects a ticket input with a nonzero index. For votes, it is dead because
CheckSSGenVotesrejects that index during classification, as noted in #3786. For revocations it is live and covered bybrt7(#3786) andTestAutoRevocations(#3787). The second site is the same for both:checkTicketSubmissionInputrejects a ticket input that references a stake output which is not a ticket submission output. Neither comment above is about this site, and nothing covered it.checkTicketRedeemersonly allows votes for winning tickets and revocations for missed or expired tickets, and the index checks pin the input to output 0, so a block can only reach the check with a real ticket submission output. The mempool doesn't runcheckTicketRedeemers, so it depends onCheckTransactionInputsto reject a vote or a revocation that references some other stake output. This is the same situation as #3797, and the test uses the same shape: it callsCheckTransactionInputsthe way the mempool does.The test mines a block that misses a vote and a block that revokes it, then repoints a vote's and a revocation's ticket input at output 0 of that revocation.