-
Notifications
You must be signed in to change notification settings - Fork 410
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 129205 +4105
Branches 125100 129205 +4105
==========================================
+ Hits 112002 116123 +4121
+ Misses 10408 10389 -19
- Partials 2690 2693 +3 ☔ 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,
/// 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
?
|
||
/// 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()
.
pub struct CurrencyCode([u8; 3]); | ||
|
||
impl CurrencyCode { | ||
/// Creates a new CurrencyCode from a 3-byte array. |
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.
s/CurrencyCode/`CurrencyCode`
Likewise in other docs.
Convert CurrencyCode from type alias to struct with validation, ensuring ISO 4217 compliance (3 ASCII uppercase letters) at construction time.
1ebbcd0
to
71562a9
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.