-
Notifications
You must be signed in to change notification settings - Fork 47
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
feat: use Uuid as mint and melt quote ids #469
Conversation
Thanks for the PR. Since the quote id being a uuid is an implementation choice and not something that is defined in the NUTs we cannot enforce or expect a mint to return and a uuid in the wallet. However, maybe for some of the reasons you stated above it would be worth using the uuid type internally for the What do you think? |
42def59
to
42209ce
Compare
@thesimplekid can you find time to review this this week? |
Yes sorry for the slow review. Will be done tomorrow. |
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.
Thank you for this PR I think its a good improvement and one to enforce early in the project.
Just a few notes on the REDB migrations but other wise LGTM.
I'm happy to migrate the sqlite but that can be a separate PR.
impl From<Params> for Vec<Index<Notification>> { | ||
fn from(val: Params) -> Self { | ||
let sub_id: SubscriptionGlobalId = Default::default(); | ||
val.filters | ||
.iter() | ||
.map(|filter| Index::from(((filter.clone(), val.kind), val.id.clone(), sub_id))) | ||
.collect() | ||
.into_iter() | ||
.map(|filter| { | ||
let idx = match val.kind { | ||
Kind::Bolt11MeltQuote => { | ||
Notification::MeltQuoteBolt11(Uuid::from_str(&filter)?) | ||
} | ||
Kind::Bolt11MintQuote => { | ||
Notification::MintQuoteBolt11(Uuid::from_str(&filter)?) | ||
} | ||
Kind::ProofState => Notification::ProofState(PublicKey::from_str(&filter)?), | ||
}; | ||
|
||
Ok(Index::from((idx, val.id.clone(), sub_id))) | ||
}) | ||
.collect::<Result<_, anyhow::Error>>() | ||
.unwrap() | ||
// TODO don't unwrap, move to try from |
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.
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.
Can I keep the unwrap
into the code for new?
I think moving to try_from will imply some changes in our custom pubsub lib, which may require rethinking part it's design, which I don't have context about and is slightly out of the scope of this PR
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.
Yes, lets do that separately. I meant that comment for @crodas
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.
We should not unwrap anything; we can either bubble up the error or exit logging it if it is unexpected (a malformed user-given input is not an error). Otherwise, it could be an attack vector that reboots the mint to flood the log with garage entries.
Having a Uuid is fine, but it shouldn't be enforced, instead hinted, as it should be backward compatible. Perhaps the ID is an enum of Uuid(Uuid), Legacy(String)
. It shouldn't be enforced unless there is a standard/NUT that enforces quotes ID to be UUIDs.
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.
We should not unwrap anything; we can either bubble up the error or exit logging it if it is unexpected (a malformed user-given input is not an error). Otherwise, it could be an attack vector that reboots the mint to flood the log with garage entries.
I agree we should not have unwraps in the codebase. Its not a question of do we keep the unwrap in the codebase its a question of do we fix this here in this PR or in your immediate follow up PR related to wallet WS #473. As changing it here may cause a lot of merge conflicts for you.
It shouldn't be enforced unless there is a standard/NUT that enforces quotes ID to be UUIDs.
This is why we don't and can't enforce it for the wallet. However for the mint it is an implementation choice that we are free to make and it has always been UUID in cdk just stored as a string and treated as a string so there are no legacy IDs.
Having a Uuid is fine, but it shouldn't be enforced, instead hinted, as it should be backward compatible. Perhaps the ID is an enum of Uuid(Uuid), Legacy(String).
I think using an enum makes it more complicated and gives flexibility we don't need to the mint as we would always use the Uuid variant of the enum. I believe it better to take an opinionated stance for the reasons @tdelabro pointed to in the description. Supporting backwards compatibility should only be done in cases where it is absolutely needed as it leads to significant tech debt that should be avoided where possible.
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 agree we should not have unwraps in the codebase. Its not a question of do we keep the unwrap in the codebase its a question of do we fix this here in this PR or in your immediate follow up PR related to wallet WS #473. As changing it here may cause a lot of merge conflicts for you.
This is not a blocked and I can improve this bit on my PR, no worries.
This is why we don't and can't enforce it for the wallet. However for the mint it is an implementation choice that we are free to make and it has always been UUID in cdk just stored as a string and treated as a string so there are no legacy IDs.
Yes, having a strict well defined type is better. String
could be a 4GB video, as long as it is a valid UTF-8 string. I like this approach. I can improve the unwraps that I don't like and add some logging in my PR.
@thesimplekid thanks for the review! I will get back to it on Monday |
42209ce
to
f101a0a
Compare
@thesimplekid ready for another 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.
/// Quote Id | ||
pub quote: String, | ||
pub quote: Q, |
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.
Instead of leaking the type as generic, isn't it better to have an ID type? And have that ID be a String or an UUID instead? /cc @thesimplekid @tdelabro
Having MeltId
wrap an String or an UUID based on a cfg.
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.
Having MeltId wrap an String or an UUID based on a cfg.
I don't think we can do it based on cfg as features are additive so both the mint
and wallet
feature could be and are by default enabled at the same time.
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.
Perhaps instead of leaking then, we can have a type MintQuoteBolt11Response<Q>
we can have a type type MintQuoteBolt11Response = nut04::MintQuoteBolt11Response<Uuid>
in the mint crate.
Other than that I like this PR.
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.
We could also keep it as a string in the Response as to be inline with the nut. And then use the uuid in only the mint mod.
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.
Yes, that could also be it, but I also like the idea of abstract generic types in a crate, then specific ones inside mint for instance, and have the webserver and future RPC use those types, but have the wallet use the generic one using a String instead.
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.
We could also keep it as a string in the Response as to be inline with the nut. And then use the uuid in only the mint mod.
Doesn't really make sense IMO.
It happens that the protocol specifies that the id can be anything that can be serialized into a string.
It happens that in some part of the codebase, we know for sure it is a Uuid, and in some other parts we don't know so we go for the smaller common denominator, a String
.
But going from bytes to String to Uuid would add an intermediate, non-necessary step in the serialization.
I don't really see any way to avoid a generic here
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.
What is the issue with having a generic? What are you trying to avoid here?
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.
There is nothing wrong, but I think it could be best and save some time at usage time to have an alias that people can reference directly.
Is readability your only issue?
Yes, pretty much yes. It was not a blocker but a minor suggestion.
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.
Let's merge it that way and see if it becomes a problem for users.
I'm usually in favor of being explicit until it becomes an overcharge of information.
Do you agree?
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'm happy with it as is.
ACK f101a0a |
Description
This PR changes the type of mint and melt quote Ids to Uuid rather than
String
.It required changes in some field types along with some trait signatures.
It will improve the code security by manipulating check Uuid, instead of string that can be anything.
It will also improve performances as Uuid fit on less memory [u8; 16] than its string representation. Same for database.
It also avoids some memory allocation by being
Copy
. So no need to clone.It also avoids mixing different types into
String
. Eg. In nut17 there was a part where both PublicKeys and Uuid were represented as the same typeString
and fed to the same method. This is really error prone and should be avoided.Notes to the reviewers
I did not write the migration to modify the Ids of the tables in the different database from string to uuid/bytes or whatever is the underlying representation.
Can you do it as you are more familiar with the multiple database supported and the way to write and test those migrations.
Suggested CHANGELOG Updates
CHANGED: use uuid as identifier for mint and melt quotes
Checklist
just final-check
before committing