-
-
Notifications
You must be signed in to change notification settings - Fork 137
feat: keysets v2 #798
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
Open
lollerfirst
wants to merge
6
commits into
cashubtc:main
Choose a base branch
from
lollerfirst:keysets-v2
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
feat: keysets v2 #798
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
0afe16c to
9a213c7
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #798 +/- ##
==========================================
+ Coverage 47.84% 49.23% +1.39%
==========================================
Files 90 92 +2
Lines 10592 11026 +434
==========================================
+ Hits 5068 5429 +361
- Misses 5524 5597 +73 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
e0a4c12 to
4cd1d78
Compare
4cd1d78 to
723eb96
Compare
Keysets v2: align with NUT-13 HMAC derivation (4-byte counter, single HMAC split); implement wallet-side short ID manager and token helpers; apply default final_expiry on rotation; keep mint agnostic of s_id
alignment
NUT-02/13 alignment:
- Keys API: include final_expiry in /v1/keys and /v1/keys/{id}
- Derivation: keyset ID v2 per spec (unit + optional final_expiry; SHA256; v=01)
- NUT-13 v2 secrets: switch to HMAC-SHA256 with 8-byte counter and type byte (00/01)
- Tests: update wallet v2 tests to HMAC-SHA256; derive seed from BIP-39 mnemonic; fix TokenV4 short ID expansion test to use KeysetManager directly; update API expectations for final_expiry
Remove mint_use_keysets_v2 flag; always generate v2 keyset IDs for new keysets. Keep optional default final_expiry via settings. Update keyset rotation/activation to use default expiry unconditionally. Update docs.
wallet: log debug when resolving short keyset id to full id (cache hit).
wallet: integrate v2 short keyset IDs directly in TokenV4 creation; deprecate WalletTokensV2 helper; tests: remove tokens_v2 dependency, assert short-ID serialization; secrets: NUT-13 v2 docstring to HMAC-SHA256; proofs: fix helper method refactor regression; cleanup
remove deprecated cashu/wallet/tokens_v2.py; short-ID handling now in WalletProofs._make_tokenv4
Summary of changes on keysets-v2
- Removed deprecated helper:
- cashu/wallet/tokens_v2.py deleted.
- Integrated short-ID handling into wallet TokenV4 creation:
- cashu/wallet/proofs.py: _make_tokenv4 now converts v2 full keyset IDs to short IDs during token creation via KeysetManager; ensured _get_proofs_mint_unit remains correct.
- Updated tests to remove tokens_v2 dependency:
- tests/wallet/test_wallet_keysets_v2.py: test_token_serialization_with_short_ids now uses WalletProofs to assert short-ID serialization.
- Docstring correction:
- cashu/wallet/secrets.py: NUT-13 v2 derivation is HMAC-SHA256 (not SHA512).
Remote
- Branch keysets-v2 is now ahead by 2 commits and pushed to origin.
format
move tests to v2 keyset id
fixed test_mint_api
more fixes
bump nutshell version to 0.18 => derive ID v1/v2 based on nutshell version of the keyset: if not specified the nutshell version is 0.18 and the keyset ID is v2
more fixes
Fix keyset version tests: update assertions for v1/v2 ID expectations
- Change test_keyset_0_15_0 and test_keyset_0_15_0_encrypted to expect V1_KEYSET_ID (version 0.15.0 uses v1 IDs)
- Update test_keyset_short_id to properly assert V1_KEYSET_ID for legacy keysets
- Simplify test_keyset_v2_deterministic to use version 0.18.0 which uses v2 IDs
- Remove redundant test_keyset_v1_v2_compatibility test (covered by other tests)
- Update test section header to 'KEYSET IDs NUT-02 TEST VECTORS'
Add comprehensive keyset ID test vectors and version behavior tests
New tests added:
1. test_keyset_versions_produce_correct_id_format: Tests that different
nutshell versions (0.11, 0.14, 0.15, 0.17, 0.18, 0.19) produce the
correct ID format (base64 for <0.15, v1 hex for 0.15-0.17, v2 hex for >=0.18)
2. test_keyset_id_v1_test_vectors: Implements NUT-02 test vectors for v1
keyset ID derivation with two test vectors (small 4-key keyset and
large 64-key keyset)
3. test_keyset_id_v2_test_vectors: Implements NUT-02 test vectors for v2
keyset ID derivation with three test vectors testing different
combinations of keyset sizes, units, and final_expiry values
These tests ensure compatibility with the NUT specifications and verify
that the keyset ID derivation algorithms produce stable, interoperable
results across different implementations.
Test vectors source: https://github.com/cashubtc/nuts/pull/182/files
Fix test_keyset_version_detection for v1 vs v2 ID distinction
Corrected the test to properly distinguish between v1 and v2 keyset IDs:
- V1 IDs (version 0.15-0.17) start with '00' and are NOT detected as v2
- V2 IDs (version 0.18+) start with '01' and ARE detected as v2
This test was incorrectly expecting a v1 keyset (version 0.15.0) to be
identified as v2.
more fixes
Add v2 short keyset ID expansion support for token redemption
Fix for TokenV3 and TokenV4 redemption with v2 short keyset IDs:
- Added _expand_short_keyset_ids() method to WalletProofs class
- Expands v2 short IDs (16 chars, '01' + 7 bytes) to full IDs (66 chars)
- Uses KeysetManager to map short->full IDs from loaded keysets
- Handles expansion failures gracefully with warning logging
- Updated redeem_TokenV3() and redeem_TokenV4() in helpers.py
- Calls _expand_short_keyset_ids() after load_mint() to ensure
all keyset IDs in proofs are expanded before redemption
- Added comprehensive test: test_proof_short_id_expansion()
- Verifies short ID expansion works correctly
- Tests that proofs with v2 short IDs get expanded to full IDs
- Fixed existing tests in test_wallet_keysets_v2.py
- Removed incorrect 'await' calls on synchronous KeysetManager methods
- Fixed test_token_v4_short_keyset_expansion to use proper v2 short ID
- Fixed test_nut13_spec_compliance to use actual V2_KEYSET_ID constant
- Updated test_wallet_cli.py token to use v2 short keyset IDs
This ensures wallets can properly handle TokenV3/V4 tokens containing
v2 short keyset IDs, which are used to reduce token size.
feat: improve v2 keyset ID handling and fee calculation
- Add short-to-full keyset ID expansion in wallet helpers
- Enhance KeysetManager with better documentation and type hints
- Fix fee calculation to handle short keyset IDs gracefully
- Add keyset ID expansion before proof redemption in CLI
- Update tests to reflect new keyset ID handling behavior
- Add fallback logic for missing keysets in fee calculations
format
fixes
base64 keysets detection
remove weird import
cannot import Unit in keys -> fix
is_base64_keyset_id fixes
simplify code and move imports on top of file
remove unnecessary ID logic in get_fees_for_keyset and get_fees_for_proofs
format
move import on top of file, error if we can't map short IDs to full IDs
bugfix: activate keysets from the DB if any
update `rotate_next_keyset` and mint management rpc with final_expiry field
723eb96 to
6b67ea8
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Keyset ID Version 2 Implementation
Warning
This PR bumps Nutshell's version to
0.19.0Overview
This PR implements the Keyset ID Version 2 specification, which changes how keyset IDs are derived and introduces support for short keyset IDs. This change improves determinism, security, and functionality of keysets while maintaining backward compatibility.
Key Changes
1. New Keyset ID Derivation
Version-based ID derivation:
00, 16 chars)01, 66 chars)V2 Keyset ID calculation:
01to indicate V2 formatunit:{unit_name})final_expiry:{timestamp})2. Short Keyset ID Support
3. Keyset Rotation Improvements
rotate_next_keysetto support thefinal_expiryparameter4. DB Fetching Rearrangement
final_expiryfield in keyset database tables5. Version-based Secret Derivation
message = "Cashu_KDF_HMAC_SHA256" || keyset_id || counterTechnical Details
Keyset ID Derivation Changes
The V2 keyset ID derivation now includes:
unit:{unit_name}to the byte arrayfinal_expiry:{timestamp}if provided01to indicate V2 formatThis creates a more robust, deterministic ID that properly includes all relevant keyset information, unlike previous versions that only used public keys.
Secret Derivation Implementation
The wallet now detects keyset version and uses the appropriate secret derivation method:
For V2 keysets (version 01):
For V1 keysets (version 00) and Base64 keysets:
The secret derivation mechanism is critical for wallet restoration and token recovery. This change ensures compatibility with all keyset formats while introducing a more robust derivation method for V2 keysets.
Rotate-Next-Keyset Behavior
When
rotate_next_keysetis called:final_expiryparameter is passed through to the new keysetKeyset Fetching Rearrangement
Previously, keysets were fetched from DB by their ID, which could cause issues when trying to load a keyset whose ID calculation might have changed. Now:
activate_keysetmethodBackward Compatibility
Testing