Skip to content

feat: enforce keyset expiry#1946

Merged
thesimplekid merged 2 commits into
cashubtc:mainfrom
gudnuf:feat/enforce-keyset-expiry
May 17, 2026
Merged

feat: enforce keyset expiry#1946
thesimplekid merged 2 commits into
cashubtc:mainfrom
gudnuf:feat/enforce-keyset-expiry

Conversation

@gudnuf
Copy link
Copy Markdown
Contributor

@gudnuf gudnuf commented Apr 28, 2026

closes #1895

Description

Enforces keyset expiry by rejecting inputs and outputs for an expired keyset. The expired keyset stays active.


Notes to the reviewers

This doesn't handle the wallet side of things. Also, while working on the tests I realized that the mint allows for keysets to be rotated with an expiry in the past, I created an issue for that #1945


Suggested CHANGELOG Updates

CHANGED

ADDED

REMOVED

FIXED


Checklist

  • I followed the code style guidelines
  • I ran just quick-check before committing
  • If the Wallet API was modified (added/removed/changed), I have reflected those changes in the FFI bindings (crates/cdk-ffi)

@github-project-automation github-project-automation Bot moved this to Backlog in CDK Apr 28, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 28, 2026

Codecov Report

❌ Patch coverage is 90.52632% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.57%. Comparing base (b3e5de8) to head (d31acec).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
crates/cdk-common/src/error.rs 0.00% 7 Missing ⚠️
crates/cdk-signatory/src/common.rs 0.00% 4 Missing ⚠️
crates/cdk/src/mint/builder.rs 0.00% 4 Missing ⚠️
crates/cdk/src/mint/mod.rs 95.16% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1946      +/-   ##
==========================================
+ Coverage   65.49%   65.57%   +0.08%     
==========================================
  Files         330      330              
  Lines       57554    57744     +190     
==========================================
+ Hits        37695    37867     +172     
- Misses      19859    19877      +18     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@TheMhv
Copy link
Copy Markdown
Contributor

TheMhv commented Apr 29, 2026

How i can test it? I try to change the active and valid_to fields directly in keyset table inside mint database but does work

@gudnuf
Copy link
Copy Markdown
Contributor Author

gudnuf commented Apr 29, 2026

How i can test it?

use the management RPC CLI to rotate

mintd-cli  rotate-next-keyset --final-expiry $(($(date +%s) + SECONDS_IN_THE_FUTURE))

Then mint ecash before SECONDS_IN_THE_FUTURE. Wait for expiry, then try to use that ecash.

I try to change the active and valid_to fields directly in keyset table inside mint database but does work

I'm not sure that works because the keyset ID commits to the expiry and mintd will auto-rotate on startup if you have no active keys. Also the mint might keep the active keys in memory.

@TheMhv
Copy link
Copy Markdown
Contributor

TheMhv commented Apr 30, 2026

The error occurs after invoice has created and paid, i think that the validation needs to be before the invoice creation.

image
image

@gudnuf
Copy link
Copy Markdown
Contributor Author

gudnuf commented Apr 30, 2026

The error occurs after invoice has created and paid, i think that the validation needs to be before the invoice creation.

Yea this is tricky because keyset can also expire after the quote is created like I described here #1895 (comment)

So we could return an error for the request to create a mint quote if the active keyset is expired, but that only solves half the problem. Do you have any suggestion on how this should work @TheMhv?

I think that this just needs to be handle client side by checking the keyset expiry.

@TheMhv
Copy link
Copy Markdown
Contributor

TheMhv commented Apr 30, 2026

Do you have any suggestion on how this should work @TheMhv?

I cannot create new mint quotes from expired keyset, the mint should return an error.

Beside that, we can has mint quotes that was created when keyset was valid, but now it's expired. For this case i have one idea, we can create a "quote renew" request that requires a payment proof (the preimage for lightning payments for example) for renew the paid mint quote to the new keyset.

@thesimplekid
Copy link
Copy Markdown
Collaborator

The error occurs after invoice has created and paid, i think that the validation needs to be before the invoice creation.

Yea this is tricky because keyset can also expire after the quote is created like I described here #1895 (comment)

So we could return an error for the request to create a mint quote if the active keyset is expired, but that only solves half the problem. Do you have any suggestion on how this should work @TheMhv?

I think that this just needs to be handle client side by checking the keyset expiry.

We could disable minting if there is no active keyset but really that doesn't always solve the problem since you could have got a mint quote before the expiry and then attempt to mint after, no check we can do can protect from that. I think its an edge case and mints generally won't be running in this state it is only if they are shutting down.

@gudnuf gudnuf force-pushed the feat/enforce-keyset-expiry branch from 963b953 to c5c22f4 Compare May 14, 2026 18:13
@thesimplekid thesimplekid force-pushed the feat/enforce-keyset-expiry branch 3 times, most recently from 2c2dee5 to d7242a9 Compare May 17, 2026 10:22
gudnuf and others added 2 commits May 17, 2026 11:23
Reject ecash from keysets whose final_expiry is in the past at every
mint operation: swap inputs/outputs, mint, melt, blind_sign, restore.

Expired keysets keep active=true and stay listed in /v1/keys and
/v1/keysets responses for backward compat with wallets that don't know
about final_expiry; those wallets discover expiry at use time via the
new Error::ExpiredKeyset (code 12003).

The mint builder no longer auto-rotates an expired active keyset, and
init_keysets does not reactivate expired keysets on startup. Both treat
expiry as the operator's shutdown signal.

Closes the enforcement half of cashubtc#1895.
@thesimplekid thesimplekid force-pushed the feat/enforce-keyset-expiry branch from d7242a9 to d31acec Compare May 17, 2026 10:23
@thesimplekid thesimplekid merged commit d31acec into cashubtc:main May 17, 2026
6 of 7 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in CDK May 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Enforce final expiry of keysetv2 keyset

3 participants