Skip to content

Conversation

@vnprc
Copy link
Contributor

@vnprc vnprc commented Aug 26, 2025

Description

Move the CurrencyUnit enum from nut00 where it was originally implemented before being added to the spec to nut01 to match the spec definition.

Implement deterministic currency unit derivation paths.

  • use SHA-256 so results are identical across platforms and rust versions
  • NFC normalization, lowercasing, and trim to ensure logically equivalent strings map to the same index
  • reserve a low integer range for known variants

Notes to the reviewers

See also this impl from the portal team: PortalTechnologiesInc@0051f57
and this impl from a previous hashpool cdk branch: vnprc@0d11a5b

The implementation in this PR improves on both of the above impls.

Suggested CHANGELOG Updates

CHANGED

ADDED

REMOVED

FIXED


Checklist

vnprc added 2 commits August 26, 2025 16:21
it is defined in the NUT-01 spec so it should live there in the code
@vnprc
Copy link
Contributor Author

vnprc commented Aug 27, 2025

Suppose we want to add a new enum value, how does that work? Do we implement it as a custom variant?

@thesimplekid
Copy link
Collaborator

Suppose we want to add a new enum value, how does that work? Do we implement it as a custom variant?

What do you mean enum value?

@vnprc
Copy link
Contributor Author

vnprc commented Aug 27, 2025

a new CurrencyUnit enum variant, like how Auth was recently added.

pub enum CurrencyUnit {
    /// Sat
    #[default]
    Sat,
    /// Msat
    Msat,
    /// Usd
    Usd,
    /// Euro
    Eur,
    /// Auth
    Auth,
    /// Custom currency unit
    Custom(String),
}

If we reserve a small range of hard coded derivation path values for the future it becomes trivial to add a new enum variant that is more ergonomic for developers to use. The downside is minor IMO: you get an infinitesimally larger chance of collision. We don't need to reserve 10,000 spaces but I think a small reserved range is a good idea.

@thesimplekid
Copy link
Collaborator

I think a small reserved range is a good idea.

for what? Even the current ones only need to stay fixed for backwards compatibility. The only point of the reserved is to map the unit to the derivation index, we can do that now by hashing.

@vnprc
Copy link
Contributor Author

vnprc commented Aug 27, 2025

It makes the code uglier. That's all.

@vnprc
Copy link
Contributor Author

vnprc commented Aug 27, 2025

I was about to suggest we take a page from the secp256k1 library and implement different hash functions but I just saw that apoelstra removed this functionality last week. rust-bitcoin/rust-secp256k1@54828ac

We could standardize on the rust default hash function for simplicity. Would this make derivation paths different in some library upgrade scenarios?

@vnprc
Copy link
Contributor Author

vnprc commented Aug 27, 2025

Discussion points from the cdk meeting:

  • we definitely want to use SHA256 to ensure consistency across architectures
  • a reserved range is not necessary for code ergonomics

@vnprc
Copy link
Contributor Author

vnprc commented Aug 27, 2025

We also determined this should be added to the NUT specs. Open question whether to add it to NUT-01 or as a new NUT.

@github-actions
Copy link
Contributor

This PR is stale because it has been open for 60 days with no activity.

@github-actions github-actions bot added the stale label Oct 27, 2025
@vnprc
Copy link
Contributor Author

vnprc commented Oct 28, 2025

cashubtc/nuts#292

@github-actions
Copy link
Contributor

This PR is stale because it has been open for 60 days with no activity.

@github-actions github-actions bot added the stale label Dec 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants