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

Enhanced error messages for invalid network prefix during address parsing. #27260

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

russeree
Copy link
Contributor

@russeree russeree commented Mar 15, 2023

Issue:

Simply DecodeDestination does not handle errors where the user inputs a valid address for the wrong network. e.x. testnet while running client on mainnet

The current error not a valid Bech32 or Base58 encoding for a valid address on a different network is entirely incorrect. This is because of the is_bech32 variable used at the core of DecodeDestination logic only checks that the prefix matches. If it doesn't it just starts running everything as DecodeBase58Check regardless if the Bech32 String was actually valid.

Proposed Solution:

Base58 Addresses with invalid prefixes will now display network and expected values.

  • previous: Invalid or unsupported Base58-encoded address.
  • 27260 Invalid or unsupported Base58 testnet address. Expected prefix m, n, or 2

Bech32 Addresses with invalid prefixes will now display network and expected values. The current from of the error is completely incorrect when the user passes valid Bech32 for the wrong network.

  • previous: Invalid or unsupported Segwit (Bech32) or Base58 encoding.
  • 27260: Invalid chain prefix for testnet. Expected tb got bc

Reference

#26290

Implementation :

Simply put, don't delay the attempt to decode the string as Bech32 using Bech32::Decode(str). This takes a minimal amount CPU cycles to perform and is acceptable to do since this operation is not performed often.

Once you get the decoding status of the string as bech32, do the same with DecodeBase58 using a len of 100 and DecodeBase58Check. This gives you enough information to start properly decoding errors.

After you have decoded the address in various formats run though the logic and display errors for invalid addresses with the network names and expected values when the user just misses the prefix.

Update 1: #27260 (comment)

Other Notes

  • Previous errors had inconsistencies such as random periods in some errors and not others. Using the word encoded in some errors and not others. This has been resolved.

@DrahtBot
Copy link
Contributor

DrahtBot commented Mar 15, 2023

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
Concept ACK Sjors
Approach ACK RandyMcMillan

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

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #30047 (refactor: Model the bech32 charlimit as an Enum by josibake)
  • #29607 (refactor: Reduce memory copying operations in bech32 encoding/decoding by paplorinc)
  • #29473 (refactor: Speed up Base58 encoding/decoding by 400%/200% via preliminary byte packing by paplorinc)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@fanquake
Copy link
Member

Please keep your changes, and "fixes" commits squashed. Looks like your changing the file perms on at least one file, is that intentional?

@russeree
Copy link
Contributor Author

Please keep your changes, and "fixes" commits squashed. Looks like your changing the file perms on at least one file, is that intentional?

Will do. No it was not intentional but was a side effect of moving 3 files over scp to a different host. This has been resolved and commits squashed.

@russeree russeree force-pushed the 26290 branch 7 times, most recently from c98f7cc to 911c8b6 Compare March 16, 2023 00:10
@russeree russeree changed the title rpc: enhanced error message for invalid network prefix during address parsing. Enhanced error messages for invalid network prefix during address parsing. Mar 16, 2023
@russeree russeree force-pushed the 26290 branch 6 times, most recently from 3c0fcda to aff7635 Compare March 19, 2023 08:50
@maflcko
Copy link
Member

maflcko commented May 18, 2023

Needs rebase on current master, if still relevant

@russeree russeree force-pushed the 26290 branch 2 times, most recently from ef46a30 to 5ff2490 Compare May 19, 2023 03:09
@russeree
Copy link
Contributor Author

Needs rebase on current master, if still relevant

I believe this PR is still very relevant because it substantially improves the logic around address decoding and specifically the displaying of errors in the GUI and RPC. With that said I have rebased and this code is passing all tests other than Win64 native [vs2022] which seems to be failing for the majority of PRs that are on master due to warnings.

@maflcko
Copy link
Member

maflcko commented May 19, 2023

Thanks, the reason I mentioned it was the silent merge conflict: key_io.cpp:152:48: error: ‘const class CChainParams’ has no member named ‘NetworkIDString’, which is now fixed

@russeree
Copy link
Contributor Author

Thanks, the reason I mentioned it was the silent merge conflict: key_io.cpp:152:48: error: ‘const class CChainParams’ has no member named ‘NetworkIDString’, which is now fixed

Is there a good way to detect these silent conflicts earlier? Usually I get notified via email when there are issues that need rebased; this is the first time one has happened without a notification.

Thanks

@russeree russeree force-pushed the 26290 branch 7 times, most recently from 0000000 to 0000000 Compare October 1, 2023 01:26
Signed-off-by: russeree <git@qrsnap.io>
@russeree russeree force-pushed the 26290 branch 4 times, most recently from 1234567 to 0000000 Compare October 1, 2023 02:55
russeree and others added 3 commits September 30, 2023 20:10
Signed-off-by: russeree <git@qrsnap.io>
Signed-off-by: russeree <git@qrsnap.io>
This commit addresses an issue in Bitcoin Core where an incorrect
bech32 prefix would lead to the address being treated as entirely
invalid for both base58 and bech32 encoding, without providing the user
with an appropriate error message. Base58 error handling was also improved.

Changes:

 - An incorrect bech32 address error message now presents the
   expected ChainParams hrp and network to the user.

 - A Bech32 address with an incorrect ChainParams prefix is
   not automatically handled as base58, increasing the accuracy
   and readability of user facing error messages.

 - An incorrect base58 address prefix now presents the user with the
   expected prefixes for the current ChainParams, which are
   deterministically computed in util/base58_address.(cpp/h)

 - Functional tests were refactored to reflect the additional accuracy
   of error messages.

 - Added GetChainTypeDisplayString(), which generates a user facing chain
   type string for "Bitcoin", "testnet", "signet", and "regtest". This is
   used for displaying the user's active chain when displaying errors.
   As per Luke Dashjr, "mainnet" is not used in user facing messages.

 - Added Base58PrefixesFromVersionBytes(), which when given a total
   length in bytes and a base58 prefix will give the user all
   possible single character prefixes for the encoded base58 string.

 - Bech32 error decoding now handles the cases where the input
   has neither base58 or bech32 characters and the inverse where the
   input has both valid base58 and bech32 characters.

 - Increased code readability through the use of structured bindings.

 - Added a multiple separators check to bech32.cpp this is to convert
   incorrect error messages about a singular separator position into
   a message that covers multiple separators and their positions.

 - Added a minimum length check to bech32.cpp and ErrorLocatiosn message
   with the locations being a vector of the chars positions up to the
   minimum length of 8 chars.

A huge thanks to D++ for the extensive contributions

Co-authored-by: D++ <82842780+dplusplus1024@users.noreply.github.com>
Signed-off-by: russeree <git@qrsnap.io>
@RandyMcMillan
Copy link
Contributor

Approach ACK

Signed-off-by: russeree <git@qrsnap.io>
Comment on lines +431 to +438
if (str.find('1') != pos) {
for(size_t search_idx = 0; search_idx < str.size(); ++search_idx) {
if(str[search_idx] == '1') {
error_locations.push_back(search_idx);
}
}
return std::make_pair("Multiple separators", std::move(error_locations));
}
Copy link
Member

Choose a reason for hiding this comment

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

In 0000000 "Add bech32 error short & multiple separators cases"

This is incorrect. 1 is an allowed character in the human readable part, hence a multiple separators check doesn't make sense. The real separator is simply the last 1 that appears. See https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32


#include <algorithm>

std::vector<char> Base58PrefixesFromVersionByte(size_t length, unsigned char version_byte)
Copy link
Member

Choose a reason for hiding this comment

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

In 0000000 "Add Base58 Address Prefix Decoder"

It seems a bit odd to me to do all of this work to compute these prefixes just for error messaging. ISTM it would be a lot simpler to just hard code them into chainparams anyways. It's not as if the prefixes will ever change, and new ones are unlikely to be added.

Merging this code seems like an additional maintenance burden for very little gain.

Also, if you insist on keeping this code, it should be placed into its final location when introduced instead of moved in the last commit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

#27260 (comment)

The choice to do this was a response to the above comment. I would agree chainparams would be the place to implement a hardcoded (char[], stringview) prefix. Another advantage is that lookup is likely faster; so if a user is frequently getting errors it may save a few them a few cycles.

@DrahtBot
Copy link
Contributor

DrahtBot commented Jun 5, 2024

🐙 This pull request conflicts with the target branch and needs rebase.

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

Successfully merging this pull request may close these issues.

None yet

8 participants