Skip to content

Release: develop -> main - #130

Merged
TaprootFreak merged 2 commits into
mainfrom
develop
May 28, 2026
Merged

Release: develop -> main#130
TaprootFreak merged 2 commits into
mainfrom
develop

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Automatic Release PR

Commits: 1 new commit(s)

  • Review all changes
  • Verify CI passes
  • Merge when ready for production

…artial migration (#128)

* fix(router): downgrade 4xx-path log calls from error to info level

The post-deploy API E2E suite hits the node with intentionally-invalid
requests to verify the 4xx validation paths. Several of these paths
called `eprintln!` (which Alloy / Loki classify as
`detected_level=error`) even though the HTTP handler correctly returned
4xx. Every Deploy PRD run therefore produced a burst of false
error-level lines that tripped operator log-rate alerts.

Switch the affected call sites to `tracing::info!` (4xx) or
`tracing::error!` (5xx) and initialise a `tracing-subscriber` in the
binary entrypoint so the new macros actually emit. Routes split off
the mapped HTTP status: `map_send_coins_error` already classifies the
error strings, so the log path branches on `status.is_server_error()`
to keep genuine prove-failure errors loud.

Affected call sites:

- `receive_coin_handler`: malformed bincode body
- `send_coin_handler`: timestamp window, signature verification,
  `Send result` breadcrumb, `send_coins error` (5xx-aware)
- `mint_handler`: `Mint prepare: ok` / `err` (5xx-aware on the err arm)
- `account_node::receive_coin_into`: success-path receipt log

5xx-class error logs (broadcast failure, DB persistence failure,
in-process state.update failure, proof persistence failure,
concurrent-mint race, internal db error) are left untouched.

* fix(router): polish — single error-mapping call, document partial migration, workspace deps

* fix(main): drop placeholder PR-cross-reference from partial-migration comment

* fix(router): collapse error log-level branches + drop redundant breadcrumbs to satisfy 100% line coverage

The previous polish (`2fe0bc2`) introduced if/else branches that route the
outer-handler error log to `tracing::error!` for 5xx-mapped status codes
and `tracing::info!` for 4xx. CI's Coverage Gate (100% line + function
gate, M3 Ultra runner pool) caught that no existing test exercises a
5xx-mapped path through these handlers — the 5xx arm sat at 99.82%
overall coverage instead of the required 100%.

Collapse: both handler error arms now emit a single `tracing::warn!`.
Rationale — a 5xx-class mapping (prover failure, unmapped string)
originates from a deeper layer that already emits its own
`tracing::error!` / `eprintln!` at the source, so this outer line is a
request-level summary; `warn` is the correct level (request failed, no
new service-side signal). A 4xx-class mapping is caller-fixable input
and `warn` is also correct there. Loki's `FieldDetector.extractLogLevel`
classifies `warn` as non-error, which matches what we want for both arms.

Also drop two redundant breadcrumb `tracing::info!` calls that no test
asserted on and that were each a pair of uncovered lines:

- `router.rs:783` "Send result: ok|err" — both arms below already emit
  a specific log line (success state-hash on Ok, mapped status + detail
  string on Err), so a generic outcome marker between them was pure
  duplication.

- `account_node.rs:238` "Receiving coin for address: aabb…" — the
  structured `tracing::info!("Persisted state. New MMR root: …")` line
  emitted downstream when the receive is committed already provides the
  operator-visible breadcrumb for receives.

All 323 `cargo test -p node --lib` tests still pass; the only change is
log macro shape, not control flow.
@github-actions github-actions Bot added the ci:full Trigger heavy CI jobs (Server + Shared Tests + Coverage Gate, ~60-90 min on M3 Ultra) label May 28, 2026
#129)

The wallet derives its BIP-32 child-index counter (`numPubkeys`)
purely from local state, which a seed restore resets to 0 — even
when the server holds `account.proof = Some(...)` from a previous
session. The next send then either (a) omits `prev_commitment_pubkey`
and gets `"prev_commitment_pubkey required for account update"`
(400) from `send_coin_handler`, or (b) re-uses pubkey[0] and
collides on the same SMT slot at commit time. Both modes surfaced
as `app/e2e/07-send.spec.ts::send-success` failing with the
mapped user-facing string `"Interner Fehler: Vorheriger Public
Key fehlt."`.

Add the authoritative counter server-side and surface it on the
balance endpoint so the wallet hydrates `numPubkeys` from the
source of truth on every balance tick:

* `Account.num_sends: u32` — bumped atomically with
  `account.proof = Some(...)` inside `send_coins_inner`. The
  `num_sends > 0 iff proof.is_some()` invariant is documented on
  the field and enforced at the only mutation site.
* `BalanceResponse.num_sends` — emitted unconditionally (default
  0 for an unobserved address, matching `Account::new()`).

Migration 0011 wipes the `accounts` table because the bincode
shape is non-additive: a pre-PR blob ends after `balance: u64`
and bincode reports "unexpected end of input" when the post-PR
deserialiser tries to read the new `num_sends` field. The closed
test env precedent for "wipe-and-replay accepts the dataloss" was
set by 0010; persisted accounts are reconstructable from the
on-chain commitment SMT + the MMR via the scanner-replay path.

Tests:

* `router_tests::balance_response_emits_num_sends_from_account`
  — verifies the handler emits the per-account counter.
* `router_tests::balance_*` — assert `num_sends == 0` on all
  unobserved/zero-balance paths.
* `api_remote::balance_response_num_sends_starts_zero_and_bumps_on_send`
  — value-bearing end-to-end check across fresh wallet → mint
  (no bump) → send (bump to 1) → commit (still 1).
@TaprootFreak
TaprootFreak merged commit b6cd48c into main May 28, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:full Trigger heavy CI jobs (Server + Shared Tests + Coverage Gate, ~60-90 min on M3 Ultra)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant