fix(bolt12): Make CurrencyCode a validated wrapper type#3814
fix(bolt12): Make CurrencyCode a validated wrapper type#3814TheBlueMatt merged 2 commits intolightningdevkit:mainfrom
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) |
TheBlueMatt
left a comment
There was a problem hiding this comment.
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)?
jkczyz
left a comment
There was a problem hiding this comment.
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. |
TheBlueMatt
left a comment
There was a problem hiding this comment.
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
jkczyz
left a comment
There was a problem hiding this comment.
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.
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.
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.
Not sure if we should just use from_utf8().expect().
There was a problem hiding this comment.
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. |
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.
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
bitcoinfuzzwithrust-lightningandCore Lightning(CLN), I noticed thatrust-lightningdoes not verify whether theoffer_currencyfield contains valid UTF-8.This commit convert
CurrencyCodefrom type alias to struct with validation, ensuringISO 4217 compliance (3 ASCII uppercase letters) at construction time.