fix(ecash): sign with the mint's SAT keyset, not whichever came first
`get_active_sat_keyset` picked the first keyset with a non-empty key map,
and `MintKeyset` had no `unit` field to filter on — so on a multi-unit mint
the wallet signed sat-denominated mint/swap requests against a usd or eur
keyset. The mint refuses that with `11013 Unit unsupported`, which is
exactly what claiming minted coins hit against testnut.cashu.space (it
serves usd, eur, msat and sat keysets). Minibits is sat-only, so this
latent bug never surfaced in production — the test-mint switch found it on
its first run.
MintKeyset now carries `unit` and `active`, both defaulted so a sat-only
mint that omits them still parses, and selection filters to sat and prefers
an active keyset.
Also: pin BIP-39 seed derivation to the specification's own test vectors.
The node's entire identity hangs off `Mnemonic::to_seed("")`, and the
`bip39` crate is no longer version-pinned (the exact pin had to be relaxed
so `cashu` could resolve). A bump that changed derivation would silently
re-key every node on the fleet and orphan every backup; both vectors —
empty passphrase and the NFKD-exercising passphrase arm — now fail the
suite instead. Verified byte-identical under the newly resolved 2.2.2.
And the route script polls the mint's quote state before claiming: the test
mint settles its own invoices, but not instantly, so claiming immediately
raced the settlement and reported a spurious "Quote not paid".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
be2cfb8293
commit
26638aa621
@@ -123,8 +123,21 @@ QUOTE="$(printf '%s' "$res" | jqf result.quote_id)"
|
||||
[ -n "$QUOTE" ] && ok "ecash-mint issued quote ${QUOTE:0:12}…" \
|
||||
|| bad "ecash-mint: $(printf '%s' "$res" | err_of)"
|
||||
|
||||
# The test mint pays its own quotes, so the claim can be attempted directly.
|
||||
# On mainnet this is expected to stay unpaid — that is not a failure.
|
||||
# The test mint settles its own invoices, but not instantly — poll the quote
|
||||
# state at the mint before claiming, or the claim races the settlement and
|
||||
# fails with "Quote not paid". On mainnet the invoice is real and nobody pays
|
||||
# it here, so staying unpaid is the expected outcome, not a failure.
|
||||
if [ -n "$QUOTE" ] && [ "$NETWORK" = testnet ]; then
|
||||
for _ in $(seq 1 20); do
|
||||
state="$(curl -s --max-time 15 "$MINT/v1/mint/quote/bolt11/$QUOTE" \
|
||||
| python3 -c "import json,sys; print((json.load(sys.stdin) or {}).get('state',''))" 2>/dev/null)"
|
||||
[ "$state" = PAID ] && break
|
||||
sleep 3
|
||||
done
|
||||
[ "$state" = PAID ] && ok "test mint settled the quote" \
|
||||
|| log " (quote still $state — claim will likely fail)"
|
||||
fi
|
||||
|
||||
if [ -n "$QUOTE" ]; then
|
||||
res="$(rpc wallet.ecash-mint-claim "{\"quote_id\":\"$QUOTE\",\"amount_sats\":16}")"
|
||||
claimed="$(printf '%s' "$res" | jqf result.amount_sats)"
|
||||
|
||||
Reference in New Issue
Block a user