Switching the sign-up work on no longer walls out an old build (relay#52) #137

Merged
paulhitt merged 2 commits from feat/pow-degrades-not-walls into main 2026-09-07 16:31:05 +00:00
paulhitt commented 2026-09-07 12:28:07 +00:00 (Migrated from gitlab.com)

Closes #52.

What was wrong

FN_SIGNUP_POW_BITS has been written, tested and off since it landed, and it could not simply be switched on. The gate refused any sign-up arriving without a challenge, so enabling it would have broken account creation for every build already in somebody's hand — and broken it invisibly, as an app that does not work.

The issue's first bullet has an answer, and it is not the one assumed

The issue asks to "confirm which shipped builds carry SignupProofOfWork (Android has it…)".

Android does not have it in the field. The published APK is 0.6, released 2026-08-31. client/src/main/kotlin/io/flamenet/client/SignupProofOfWork.kt was added 2026-09-01 — one day later. iOS has it on main and has not shipped at all.

So the shipped floor on both platforms is a client that cannot answer a challenge, which is exactly the case the wall would have hit.

What changed

A client that sends no challenge now drops to a strict per-address allowance instead of being refused:

allowance
answers the challenge FN_SIGNUP_MAX_PER_HOUR — 50/hr
cannot answer FN_SIGNUP_MAX_PER_HOUR_WITHOUT_POW — 5/hr
answers it wrong refused, challenge_failed

Five per address per hour is the accidental backstop that existed before relay#9 raised the limit to 50 — restored, but only for callers that cannot do the work rather than for everybody. Doing the work is what buys the generous allowance, so the opt-out costs something.

A wrong answer is still refused outright. Sending garbage must not be a cheaper route to the lenient path than sending nothing, or the work is optional for anyone who reads the file.

0 restores the wall — the right setting once both shipped clients solve challenges, and deliberately still reachable.

Falsified, not just passed

Six new tests. Both halves were checked against the unfixed code:

  • disabling the fallback branch → a client that cannot answer still gets an account and skipping the work drops the caller to the strict allowance both go red with challenge_required
  • charging the generous limit in the fallback instead of the strict one → the second goes red on its own: an error was expected but none was thrown

19/19 in the file, locally.

Honest about what this buys

Per-address is trivially rotated, so the strict fallback bounds a lazy attacker and not a determined one. That limit is written into the code comment, not only here. The gain is not that the fallback is strong — it is that the strong thing can now be enabled at all, without stranding real people on an old build.

Not done here

Actually setting FN_SIGNUP_POW_BITS in production. That is now safe for shipped clients and is an ops decision, so it is left to be taken deliberately rather than smuggled into a code change.

Closes #52. ## What was wrong `FN_SIGNUP_POW_BITS` has been written, tested and **off** since it landed, and it could not simply be switched on. The gate refused any sign-up arriving without a challenge, so enabling it would have broken account creation for every build already in somebody's hand — and broken it invisibly, as an app that does not work. ## The issue's first bullet has an answer, and it is not the one assumed The issue asks to *"confirm which shipped builds carry `SignupProofOfWork` (Android has it…)"*. **Android does not have it in the field.** The published APK is 0.6, released **2026-08-31**. `client/src/main/kotlin/io/flamenet/client/SignupProofOfWork.kt` was added **2026-09-01** — one day later. iOS has it on `main` and has not shipped at all. So the shipped floor on *both* platforms is a client that cannot answer a challenge, which is exactly the case the wall would have hit. ## What changed A client that sends no challenge now drops to a strict per-address allowance instead of being refused: | | allowance | |---|---| | answers the challenge | `FN_SIGNUP_MAX_PER_HOUR` — 50/hr | | cannot answer | `FN_SIGNUP_MAX_PER_HOUR_WITHOUT_POW` — 5/hr | | answers it **wrong** | refused, `challenge_failed` | Five per address per hour is the accidental backstop that existed before relay#9 raised the limit to 50 — restored, but only for callers that cannot do the work rather than for everybody. **Doing the work is what buys the generous allowance**, so the opt-out costs something. A *wrong* answer is still refused outright. Sending garbage must not be a cheaper route to the lenient path than sending nothing, or the work is optional for anyone who reads the file. `0` restores the wall — the right setting once both shipped clients solve challenges, and deliberately still reachable. ## Falsified, not just passed Six new tests. Both halves were checked against the *unfixed* code: - disabling the fallback branch → *a client that cannot answer still gets an account* and *skipping the work drops the caller to the strict allowance* both go red with `challenge_required` - charging the generous limit in the fallback instead of the strict one → the second goes red on its own: `an error was expected but none was thrown` 19/19 in the file, locally. ## Honest about what this buys Per-address is trivially rotated, so the strict fallback bounds a lazy attacker and not a determined one. That limit is written into the code comment, not only here. The gain is not that the fallback is strong — it is that **the strong thing can now be enabled at all**, without stranding real people on an old build. ## Not done here Actually setting `FN_SIGNUP_POW_BITS` in production. That is now safe for shipped clients and is an ops decision, so it is left to be taken deliberately rather than smuggled into a code change.
paulhitt commented 2026-09-07 13:40:01 +00:00 (Migrated from gitlab.com)

added 4 commits

  • 487efd18...7e1792f6 - 2 commits from branch main
  • 01625a6c - Switching the sign-up work on no longer walls out an old build (relay#52)
  • a0687864 - Regenerate the configuration page after editing its source

Compare with previous version

added 4 commits <ul><li>487efd18...7e1792f6 - 2 commits from branch <code>main</code></li><li>01625a6c - Switching the sign-up work on no longer walls out an old build (relay#52)</li><li>a0687864 - Regenerate the configuration page after editing its source</li></ul> [Compare with previous version](/paulhitt/flamenet-relay/-/merge_requests/74/diffs?diff_id=2009243271&start_sha=487efd187fd9769fdfec04f562418ee26b24f606)
paulhitt commented 2026-09-07 16:31:05 +00:00 (Migrated from gitlab.com)

mentioned in commit ebea63a3ff

mentioned in commit ebea63a3ff430ab4b1937ba8ac60c06765cd919a
paulhitt (Migrated from gitlab.com) merged commit ebea63a3ff into main 2026-09-07 16:31:05 +00:00
paulhitt commented 2026-09-09 18:58:49 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
Sign in to join this conversation.