Skip to content
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

rename TransactionError:ALREADY_IN_CHAIN #30212

Merged
merged 2 commits into from
Aug 6, 2024

Conversation

willcl-ark
Copy link
Member

@willcl-ark willcl-ark commented May 31, 2024

Closes: #19363

Renaming this error improves clarity around the returned error both internally and externally when a transactions' outputs are already found in the utxo set (TransactionError::ALREADY_IN_CHAIN -> TransactionError::ALREADY_IN_UTXO_SET)

@DrahtBot
Copy link
Contributor

DrahtBot commented May 31, 2024

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage

For detailed information about the code coverage, see the test coverage report.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK tdb3, ismaelsadeeq, ryanofsky
Stale ACK theStack

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

Conflicts

No conflicts as of last run.

@willcl-ark
Copy link
Member Author

This addresses #19363 's concern:

If a transaction is already in the block chain, and all of its outputs are spent, the BroadcastTransaction() fails to detect the correct transaction status. It returns TransactionError::MISSING_INPUTS instead of TransactionError::ALREADY_IN_CHAIN.

...by now returning TransactionError::INPUTS_MISSING_OR_SPENT. The translation for this error message already indicated this error may mean the inputs were missing or spent.

Copy link
Contributor

@theStack theStack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept and code-review ACK aa422bc

I agree that the proposed names are more to the point and less confusing.

Copy link
Member

@ismaelsadeeq ismaelsadeeq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review ACK aa422bc

@@ -22,7 +22,7 @@ static TransactionError HandleATMPError(const TxValidationState& state, std::str
err_string_out = state.ToString();
if (state.IsInvalid()) {
if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
return TransactionError::MISSING_INPUTS;
Copy link
Member

@ismaelsadeeq ismaelsadeeq Jun 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, I think we should also rename the one in TxValidationResult enum.

g/TX_MISSING_INPUTS/TX_MISSING_INPUT_OR_SPENT/g
and update comments appropriately.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did consider this, but it felt much less exposed to the user, only via testmempoolaccept AFAIK:

    result_inner.pushKV("reject-reason", "missing-inputs");

Therefore as an "internal error", TX_MISSING_INPUTS (for any reason) it felt more accurate to me to leave as is? Very happy to be persuaded away from this viewpoint though :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Therefore as an "internal error", TX_MISSING_INPUTS (for any reason) it felt more accurate to me to leave as is?

I was reviewing this based on the PR rationale in the OP. You stated that "a transaction's inputs are missing from the UTXO set, which could also be due to all inputs having already been spent (MISSING_INPUTS -> INPUTS_MISSING_OR_SPENT)." That's why I suggested that TxValidationResult one should be changed just for uniformity. But Internally, you're right TX_MISSING_INPUTS inferred or spent.

Maybe just update the testmempoolaccept reject reason since it's user-facing?

But if you agree, you may have to update some functional tests that use it and maybe a release note since users heavily use the RPC.

This is a non blocking comment.

This PR is an improvement and will close the issue

Copy link
Member

@maflcko maflcko Jul 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also don't understand why the first commit is needed. The error message is already correct (and unchanged in this pull request): Untranslated("Inputs missing or spent").

I'd say it is fine to drop the commit (or keep it if you want). Just a style nit, either is fine.

@willcl-ark
Copy link
Member Author

Rebased on master to fix merge conflict.

Added an extra commit to cover PSBTError::MISSING_INPUTS.

Copy link
Member

@ismaelsadeeq ismaelsadeeq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re-ACK b2b4b93

@DrahtBot DrahtBot requested a review from theStack June 14, 2024 15:45
Copy link
Contributor

@theStack theStack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re-ACK b2b4b93

@willcl-ark willcl-ark force-pushed the clarify-missing-inputs-err branch from b2b4b93 to 77ef75d Compare June 21, 2024 11:04
Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review ACK 77ef75d if test failure is fixed (see comment below)

Note: I didn't totally follow the original issue or how these changes resolve it, but all the changes here seem reasonable regardless.

src/common/messages.cpp Outdated Show resolved Hide resolved
@ryanofsky
Copy link
Contributor

Code review ACK a05f4ca.

Just changed psbt error string and fixed a test since the last review.

Copy link
Contributor

@tdb3 tdb3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approach ACK
Good work increasing clarity. In the past I've had a head-scratching moment with some of these before I learned the nuances, so this should help people.

Left a comment about release notes.

Tested:

  • Ran unit/functional tests locally (passed)
  • Manually exercised the following scenario (regtest):
    • Created a transaction (and broadcasted).
    • Generated one block to confirm.
    • Attempted to call sendrawtransaction with the newly confirmed transaction.
    • Received Transaction outputs already in UTXO set as expected.
    • Performed sendall to spent all UTXOs.
    • Re-attempted to call sendrawtransaction with the the spent transaction.
    • Received bad-txns-inputs-missingorspent

self.generate(self.nodes[2], 1)
for node in self.nodes:
testres = node.testmempoolaccept([tx['hex']])[0]
assert_equal(testres['allowed'], False)
assert_equal(testres['reject-reason'], 'txn-already-known')
assert_raises_rpc_error(-27, 'Transaction already in block chain', node.sendrawtransaction, tx['hex'])
assert_raises_rpc_error(-27, 'Transaction outputs already in utxo set', node.sendrawtransaction, tx['hex'])
Copy link
Contributor

@tdb3 tdb3 Jul 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although it's only the error message (and the number stays the same), I still think its appropriate to add a release note for the change to the user.

https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md#release-notes

Release notes should be written for any PR that:
...
makes any other visible change to the end-user experience.

Copy link
Member

@maflcko maflcko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a question. Also, I don't think this is a "refactor"

@@ -22,7 +22,7 @@ static TransactionError HandleATMPError(const TxValidationState& state, std::str
err_string_out = state.ToString();
if (state.IsInvalid()) {
if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
return TransactionError::MISSING_INPUTS;
Copy link
Member

@maflcko maflcko Jul 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also don't understand why the first commit is needed. The error message is already correct (and unchanged in this pull request): Untranslated("Inputs missing or spent").

I'd say it is fine to drop the commit (or keep it if you want). Just a style nit, either is fine.

RPC_IN_WARMUP = -28, //!< Client still warming up
RPC_METHOD_DEPRECATED = -32, //!< RPC method is deprecated

//! Aliases for backward compatibility
RPC_TRANSACTION_ERROR = RPC_VERIFY_ERROR,
RPC_TRANSACTION_REJECTED = RPC_VERIFY_REJECTED,
RPC_TRANSACTION_ALREADY_IN_CHAIN= RPC_VERIFY_ALREADY_IN_CHAIN,
RPC_TRANSACTION_ALREADY_IN_CHAIN= RPC_VERIFY_ALREADY_IN_UTXO_SET,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

95b09ed: The second commit is not a refactor, but claims to be one. However, it changes the rpc error messages. Also, it is removing the RPC_VERIFY_ALREADY_IN_CHAIN from this header. Either this is fine, in which case this whole "backward compat" section can be removed, or it is not fine, in which case the symbol needs to be restored. C.f. d29a291

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re: #30212 (comment)

Good catch. It is inconsistent to have added backwards compatible aliases previously when renaming and not add them now when renaming again. But it looks like the backwards compatibility section was added in 2014 when it was might have less clear whether aliases were needed. I'd say now aliases are probably not needed and it would be better to remove this section.

case PSBTError::MISSING_INPUTS:
return Untranslated("Inputs missing or spent");
case PSBTError::INPUTS_INVALID:
return Untranslated("Invalid inputs");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a05f4ca: This commit is not a refactor either.

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree on not calling the commits which change error messages refactoring. I do like first commit making error constant more consistent with error message, but agree it is not essential.

RPC_IN_WARMUP = -28, //!< Client still warming up
RPC_METHOD_DEPRECATED = -32, //!< RPC method is deprecated

//! Aliases for backward compatibility
RPC_TRANSACTION_ERROR = RPC_VERIFY_ERROR,
RPC_TRANSACTION_REJECTED = RPC_VERIFY_REJECTED,
RPC_TRANSACTION_ALREADY_IN_CHAIN= RPC_VERIFY_ALREADY_IN_CHAIN,
RPC_TRANSACTION_ALREADY_IN_CHAIN= RPC_VERIFY_ALREADY_IN_UTXO_SET,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re: #30212 (comment)

Good catch. It is inconsistent to have added backwards compatible aliases previously when renaming and not add them now when renaming again. But it looks like the backwards compatibility section was added in 2014 when it was might have less clear whether aliases were needed. I'd say now aliases are probably not needed and it would be better to remove this section.

@@ -704,7 +704,7 @@ def test_psbt_input_keys(psbt_input, keys):
assert_equal(analysis['next'], 'creator')
assert_equal(analysis['error'], 'PSBT is not valid. Input 0 specifies invalid prevout')

assert_raises_rpc_error(-25, 'Inputs missing or spent', self.nodes[0].walletprocesspsbt, 'cHNidP8BAJoCAAAAAkvEW8NnDtdNtDpsmze+Ht2LH35IJcKv00jKAlUs21RrAwAAAAD/////S8Rbw2cO1020OmybN74e3Ysffkglwq/TSMoCVSzbVGsBAAAAAP7///8CwLYClQAAAAAWABSNJKzjaUb3uOxixsvh1GGE3fW7zQD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XIAAAAAAAEAnQIAAAACczMa321tVHuN4GKWKRncycI22aX3uXgwSFUKM2orjRsBAAAAAP7///9zMxrfbW1Ue43gYpYpGdzJwjbZpfe5eDBIVQozaiuNGwAAAAAA/v///wIA+QKVAAAAABl2qRT9zXUVA8Ls5iVqynLHe5/vSe1XyYisQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAAAAAQEfQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAA==')
assert_raises_rpc_error(-25, 'Invalid inputs', self.nodes[0].walletprocesspsbt, 'cHNidP8BAJoCAAAAAkvEW8NnDtdNtDpsmze+Ht2LH35IJcKv00jKAlUs21RrAwAAAAD/////S8Rbw2cO1020OmybN74e3Ysffkglwq/TSMoCVSzbVGsBAAAAAP7///8CwLYClQAAAAAWABSNJKzjaUb3uOxixsvh1GGE3fW7zQD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XIAAAAAAAEAnQIAAAACczMa321tVHuN4GKWKRncycI22aX3uXgwSFUKM2orjRsBAAAAAP7///9zMxrfbW1Ue43gYpYpGdzJwjbZpfe5eDBIVQozaiuNGwAAAAAA/v///wIA+QKVAAAAABl2qRT9zXUVA8Ls5iVqynLHe5/vSe1XyYisQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAAAAAQEfQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAA==')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "refactor: PSBTError::MISSING_INPUTS" (a05f4ca)

I wonder if "invalid transaction inputs" might be a clearer message for a user than "invalid inputs." (I had suggested "invalid inputs" but in this context it seems vague.)

Copy link
Member

@ismaelsadeeq ismaelsadeeq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good to me 🥇

I will re-ACK after comments were addressed

@willcl-ark willcl-ark force-pushed the clarify-missing-inputs-err branch from a05f4ca to 76eb6f3 Compare August 5, 2024 13:01
@DrahtBot
Copy link
Contributor

DrahtBot commented Aug 5, 2024

🚧 At least one of the CI tasks failed.
Debug: https://github.com/bitcoin/bitcoin/runs/28352468859

Hints

Make sure to run all tests locally, according to the documentation.

The failure may happen due to a number of reasons, for example:

  • Possibly due to a silent merge conflict (the changes in this pull request being
    incompatible with the current code in the target branch). If so, make sure to rebase on the latest
    commit of the target branch.

  • A sanitizer issue, which can only be found by compiling with the sanitizer and running the
    affected test.

  • An intermittent issue.

Leave a comment here, if you need help tracking down a confusing failure.

When using `sendrawtransaction` the ALREADY_IN_CHAIN error help string
may be confusing.

Rename TransactionError::ALREADY_IN_CHAIN to
TransactionError::ALREADY_IN_UTXO_SET and update the rpc help string.

Remove backwards compatibility alias as no longer required.
@willcl-ark willcl-ark force-pushed the clarify-missing-inputs-err branch from 76eb6f3 to e9de0a7 Compare August 5, 2024 14:46
@willcl-ark willcl-ark changed the title rename TransactionErrors: MISSING_INPUTS and ALREADY_IN_CHAIN rename TransactionError:ALREADY_IN_CHAIN Aug 5, 2024
@DrahtBot DrahtBot removed the CI failed label Aug 5, 2024
Copy link
Contributor

@tdb3 tdb3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK e9de0a7
Re-ran tests in #30212 (review) (successful)

Copy link
Member

@ismaelsadeeq ismaelsadeeq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK e9de0a7

@willcl-ark
Copy link
Member Author

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review ACK e9de0a7.

Since last review, change has been simplified, no longer renaming PSBTError::MISSING_INPUTS to PSBTError::INPUTS_INVALID and no longer renaming TransactionError::MISSING_INPUTS to TransactionError::INPUTS_MISSING_OR_SPENT

I did think both of those renames were improvements, but it does simplify the PR to drop them. Also it makes it easier to see how this PR fixes #19363.

Also release notes were added

@@ -43,7 +43,7 @@ static RPCHelpMan sendrawtransaction()
"\nThe transaction will be sent unconditionally to all peers, so using sendrawtransaction\n"
"for manual rebroadcast may degrade privacy by leaking the transaction's origin, as\n"
"nodes will normally not rebroadcast non-wallet transactions already in their mempool.\n"
"\nA specific exception, RPC_TRANSACTION_ALREADY_IN_CHAIN, may throw if the transaction cannot be added to the mempool.\n"
"\nA specific exception, RPC_TRANSACTION_ALREADY_IN_UTXO_SET, may throw if the transaction cannot be added to the mempool.\n"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "rpc: clarify ALREADY_IN_CHAIN rpc errors" (87b1880)

Was already the case before this PR, but this documentation seems misleading because "already in utxo set" error is not the only error that can be triggered if transaction can't be added to the mempool.

As #19363 reports BroadcastTransaction will start returning MISSING_INPUTS instead of ALREADY_IN_UTXO_SET after the outputs are spent. Also it looks like BroadcastTransaction can returns MEMPOOL_REJECTED and MEMPOOL_ERROR which get translated into RPC_TRANSACTION_REJECTED and RPC_TRANSACTION_ERROR. So 3 different error codes may be returned if the transaction can't be added to the mempool, not just 1

@ryanofsky ryanofsky merged commit 870447f into bitcoin:master Aug 6, 2024
16 checks passed
@Roasbeef
Copy link

Does bitcoind consider this to be a breaking change? The new error message may be "more accurate", but for clients that were matching on this error to figure out why a transaction was rejected, this breaks old behavior.

Alternatively, the error constant could be renamed, with the error text/string left in place.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

TransactionError::ALREADY_IN_CHAIN inconsistency
8 participants