Skip to content

chore: Replace infogetty cpp with a Rust version - #11881

Merged
Bownairo merged 3 commits into
masterfrom
eero/remove-cpp
Oct 28, 2026
Merged

Bownairo merged 3 commits into
masterfrom
eero/remove-cpp

Conversation

@Bownairo

@Bownairo Bownairo commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Translate the cpp infogetty into Rust, so we can remove the last remaining cpp builds from the repo.

@Bownairo
Bownairo force-pushed the eero/remove-cpp branch 2 times, most recently from 2f896f5 to b87313c Compare October 16, 2026 23:49
@Bownairo Bownairo changed the title Replace infogetty cpp with a Rust version chore: Replace infogetty cpp with a Rust version Oct 16, 2026
@github-actions github-actions Bot added the chore label Oct 16, 2026
@Bownairo
Bownairo force-pushed the eero/remove-cpp branch 2 times, most recently from def23cb to 7c465bf Compare October 16, 2026 23:57
Comment thread rs/ic_os/infogetty/src/main.rs Resolved
@Bownairo
Bownairo marked this pull request as ready for review October 19, 2026 21:15
@Bownairo
Bownairo requested review from a team as code owners October 19, 2026 21:15
@zeropath-ai

zeropath-ai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

✅ No security or compliance issues detected. Reviewed everything up to 3c1021d.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► Cargo.Bazel.json.lock
    Update in-lockfile checksums and add new targets (ios, netdev, block2, dispatch2, plist, quick-xml, crossterm, mac_addr, netlink-related crates)
Enhancement ► Cargo.Bazel.toml.lock
    Add new crates and versions (block2 0.6.2, crossterm 0.29.0, netdev 0.46.3, dispatch2 0.3.1, plist 1.10.3, dlopen2 0.8.2, document-features 0.2.12, objc2-related crates)
Enhancement ► Cargo.lock
    Bump dependencies to include crossterm 0.29.0 and netdev 0.46.3 among others; update related crates (quick-xml, mac-addr, litrs, plist, plist-related updates)
Enhancement ► Cargo.toml
    Add rs/ic_os/infogetty module to workspace; add dependency on crossterm 0.29.0; include netdev in dev/test dependencies; enable features for rustix 1.1.4 and related crates
Enhancement ► bazel/rust.MODULE.bazel
    Register crate specs for crossterm 0.29.0 and netdev 0.46.3; adjust rust toolchain module for rustix 1.1.4
Enhancement ► cpp/ files (deleted): removed infogetty build setup (cpp/BUILD.bazel, cpp/Makefile, cpp/infogetty-cpp/infogetty.cc)

q-uint pushed a commit to Swiss-Subnet/ic that referenced this pull request Oct 20, 2026
…#11899)

## Root cause

`core::test::test_startup` starts Pebble (Let's Encrypt's ACME test
server) and then ic-boundary with an ACME TLS-ALPN-01 certificate
resolver. It then polls `https://127.0.0.1:5001/health` for up to 240 s,
until ic-boundary serves the certificate it got from Pebble. Both flaky
runs of the last week (merge queue on 2026-10-15, dfinity#11881 on 2026-10-19)
failed their first attempt with `Unable to query ic-boundary: timed
out`. The Pebble log interleaved in the test log shows ic-boundary
abandoning 8 ACME orders in a row.

ic-boundary only gets its certificate by luck:

1. rustls-acme 0.15.4 (used through ic-bn-lib's `AcmeAlpn`) POSTs the
challenge, waits 1 s and polls the authorization. If it is still
`pending`, it POSTs the challenge again
([`state.rs`](https://github.com/FlorianUekermann/rustls-acme/blob/main/src/state.rs),
unchanged on upstream `main`).
2. By default, Pebble's validation authority runs 3 validations per
challenge, each after a random 0-4 s sleep (`rand.Intn(5)`). Meanwhile
the challenge is `processing`, so Pebble answers the second POST with
`400 malformed: Cannot update challenge with status processing, only
status pending`.
3. rustls-acme treats the 400 as an order error. It abandons the order
and starts a new one after an exponential backoff of 1, 2, 4, 8, … s.
4. An order succeeds only in two cases:
- all 3 sleeps are short enough (max 0-1 s, at most 6.4% of orders) for
validation to finish before the 1 s poll;
- Pebble reuses a valid authorization left behind by an abandoned order.
It does this for 51% of new orders (`PEBBLE_AUTHZREUSE` defaults to 50,
applied as `rand.Intn(100) > 50`).

Abandoned authorizations become valid because rustls-acme leaves the
challenge certificate in its single challenge slot when an order errors.
When the next order replaces it before Pebble's delayed validation runs,
that validation fails. This causes the `authz ... set INVALID` lines in
the logs, which dfinity#9197 took for the cause.

With the backoff, 240 s fits 8 orders, starting about 0, 2, 6, 12, 21,
38, 71 and 137 s in; a 9th would start at about 267 s. dfinity#9197 raised the
budget from 120 s to 240 s, which only added the 8th order.

Evidence:

- **CI history.** Since dfinity#9197, 19 of about 1,450 CI executions of this
target (remote-cache hits excluded) were FLAKY. Their BuildBuddy console
logs show:
  - 16 runs with exactly this pattern: 8 orders, each abandoned;
  - 3 runs with a different cause (see "Not addressed here");
  - only `test_startup` failed in all of them.
- **Model.** A Monte Carlo model of the flow, fitted to the logs'
timings, gives a 1.7% first-attempt failure rate per execution, and 3.5%
with the old 120 s budget.
- **Local runs.** Runs of `core::test::test_startup` with Pebble's
settings varied through `--test_env`:

| Pebble environment | passed | orders per run, mean (max) | time to
certificate, median (max) |
|---|---|---|---|
| defaults (master) | 30/30 | 4.6 (8) | 22 s (139 s) |
| `PEBBLE_AUTHZREUSE=0` | **3/10** | 6.9 (8) | the 7 failures timed out
after 8 orders, as in CI |
| `PEBBLE_VA_NOSLEEP=1` + `PEBBLE_AUTHZREUSE=0` | 30/30 | 1.1 (2) | 3 s
(6 s) |
| `PEBBLE_VA_NOSLEEP=1` | 30/30 | 1.0 (1) | 3 s (4 s) |

## Fix

Set `PEBBLE_VA_NOSLEEP=1` in the test's environment. ic-bn-lib spawns
Pebble as a child process, so Pebble inherits it and validates the
challenge right away. rustls-acme's first poll then finds the
authorization valid. Pebble still performs the real TLS-ALPN-01
validation against ic-boundary's resolver (unlike
`PEBBLE_VA_ALWAYS_VALID`), so the test keeps covering it.

One source of randomness remains. ic-bn-lib makes Pebble reject 1% of
nonces, and rustls-acme doesn't retry a `badNonce`, so an order of 9
signed requests still fails about 9% of the time. The next order starts
1 s later.

Verification on this branch:

- `bazel test --runs_per_test=3 --jobs=3`: 3/3 passed, about 4 s each.
- `--runs_per_test=50` of the whole target: 50/50 passed, at most 7.5 s;
the certificate arrived after a median of 3 s and at most 7 s.
- Every log has Pebble's `Disabling random VA sleeps` line and no
`Sleeping for` lines.

## Not addressed here

- **Port 34000.** 3 of the 19 flaky runs since dfinity#9197 (2026-05-08, 07-10
and 07-24) failed because Pebble could not bind its port: `listen tcp
127.0.0.1:34000: bind: address already in use`. ic-bn-lib's Pebble
helper hard-codes ports 34000, 38053 and 38055, all inside Linux's
ephemeral port range (32768-60999). Fixing it needs an ic-bn-lib change:
ports below 32768, or retrying startup.
- **rustls-acme upstream.** It shouldn't POST a challenge again while it
is being validated, and it should retry `badNonce`. Let's Encrypt's
Boulder rejects such a repeated challenge POST with `Authorization is
already being validated` when its `SetAuthzProcessing` feature is
enabled. Whether Let's Encrypt runs with that enabled in production is
unknown.

---

This PR was created following the steps in
`.claude/skills/fix-flaky-tests/SKILL.md`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@Bownairo
Bownairo enabled auto-merge October 20, 2026 16:30

@blind-oracle blind-oracle left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trust the LLM!

@Bownairo
Bownairo added this pull request to the merge queue Oct 28, 2026
Merged via the queue into master with commit 7c7a7e8 Oct 28, 2026
38 checks passed
@Bownairo
Bownairo deleted the eero/remove-cpp branch October 28, 2026 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants