-
Notifications
You must be signed in to change notification settings - Fork 411
fix(bolt12): Make CurrencyCode a validated wrapper type #3814
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
base: main
Are you sure you want to change the base?
fix(bolt12): Make CurrencyCode a validated wrapper type #3814
Conversation
👋 Thanks for assigning @jkczyz as a reviewer! |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3814 +/- ##
==========================================
+ Coverage 89.52% 89.87% +0.34%
==========================================
Files 157 160 +3
Lines 125100 129412 +4312
Branches 125100 129412 +4312
==========================================
+ Hits 112002 116311 +4309
+ Misses 10408 10396 -12
- Partials 2690 2705 +15 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
7232027
to
748747b
Compare
I took a closer look, and it seems this test vector has an invalid currency length in UTF-8 encoding, rather than being an invalid UTF-8 string itself.
data part: Looking at the data part, we observe 06 (currency type), 02 (length), and 8041 (value), which confirms that the error arises from an invalid currency length in UTF-8 encoding, not from an invalid UTF-8 sequence. I'll open a PR on Bolts to fix it. (edited) |
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.
Aren't the currencies supposed to be the three-char currency specification standard? ie they should be ASCII only (and probably all-caps letter only, never numbers)?
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.
Thanks for jumping on this!
Ah, yeah either the test vector or the comment is wrong lol |
Initially, I considered just aligning it with the UTF-8 type for consistency. But yes, it makes more sense to enforce stricter validation to ensure it's valid ASCII and adheres to the expected format. |
748747b
to
91e633a
Compare
🔔 1st Reminder Hey @TheBlueMatt @jkczyz! This PR has been waiting for your review. |
Ah, funny, seems this fixes #3813 we just opened. Will link the issue. |
No, it's 06 (currency type), 02 (length), and 8041 (value). It seems that you've copied the '2' to read '2804'. |
Yes, My mistake on the transcription. It's invalid UTF-8, but the decoder fails due to the length mismatch (expecting 3 bytes for currency) rather than the UTF-8 validation itself. |
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.
Rather than checking this when deserializing an offer, can we change CurrencyCode
to be a real wrapper so that we can enforce it on creation/deserialization of that struct? Currently I believe we will let users build offers that we will refuse to parse.
🔔 1st Reminder Hey @jkczyz! This PR has been waiting for your review. |
They would be helpful as upcoming |
d9b2684
to
1ebbcd0
Compare
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.
Will defer to @TheBlueMatt on some of these comments,
lightning/src/offers/offer.rs
Outdated
/// Creates a new CurrencyCode from a 3-byte array. | ||
/// | ||
/// Returns an error if the bytes are not valid UTF-8 or not all ASCII uppercase. | ||
pub fn new(code: [u8; 3]) -> Result<Self, Bolt12SemanticError> { |
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.
Should we use the unit type ()
for the error given and map at the call site given it can't be any other variant than InvalidCurrencyCode
?
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 have created a new custom error type for parsing it.
lightning/src/offers/offer.rs
Outdated
|
||
/// Returns the currency code as a string slice. | ||
pub fn as_str(&self) -> &str { | ||
unsafe { core::str::from_utf8_unchecked(&self.0) } |
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.
Not sure if we should just use from_utf8().expect()
.
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.
Yea, while its safe, there's also not much reason to bother with the optimization of skipping UTF-8 validation on a 3-char string (even if it would marginally reduce the binary size by avoiding the unwrap
line and/or error string).
41929f5
to
46cbed5
Compare
🔔 2nd Reminder Hey @TheBlueMatt @jkczyz! This PR has been waiting for your review. |
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.
Thanks!
lightning/src/offers/offer.rs
Outdated
|
||
/// Returns the currency code as a string slice. | ||
pub fn as_str(&self) -> &str { | ||
unsafe { core::str::from_utf8_unchecked(&self.0) } |
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.
Yea, while its safe, there's also not much reason to bother with the optimization of skipping UTF-8 validation on a 3-char string (even if it would marginally reduce the binary size by avoiding the unwrap
line and/or error string).
87c2752
to
e2c14e1
Compare
Convert CurrencyCode from type alias to struct with validation, ensuring ISO 4217 compliance (3 ASCII uppercase letters) at construction time.
Tests cover UTF-8 validation, ASCII uppercase validation, case sensitivity, length checks, and API consistency between new() and from_str().
e2c14e1
to
388c5d5
Compare
After performing differential fuzzing using
bitcoinfuzz
withrust-lightning
andCore Lightning
(CLN), I noticed thatrust-lightning
does not verify whether theoffer_currency
field contains valid UTF-8.This commit convert
CurrencyCode
from type alias to struct with validation, ensuringISO 4217 compliance (3 ASCII uppercase letters) at construction time.