Merge main-v0.14.3 into main - #14883
Conversation
…ion (#14664) Replace the immediate try_acquire load-shed with a bounded FIFO queue: when all workers are busy, a request waits its turn for a slot instead of being rejected the instant the prover is at capacity. - Two semaphores: admission caps total in-flight (running + waiting) so the queue can't grow without bound; concurrency caps actual provers. - Admission returns -32005 only when the queue is full. - Admitted requests wait FIFO (tokio's Semaphore is fair) for a worker slot, up to a backstop queue_wait_timeout (default 30s, ~the client timeout) so a stuck worker can't pin a waiter's connection; otherwise served in arrival order, or cancelled if the client disconnects. New config max_queued_requests (default 8, the primary shedding knob) and queue_wait_timeout_millis (default 30_000, backstop only); max_queued = 0 reproduces the previous immediate-reject behavior. -32005 still composes with the SDK's retry. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…errides (#14673) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…0000ms, fail_open=false) (#14671) * starknet_transaction_prover: bump default blocking_check_timeout_millis to 10000 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * starknet_transaction_prover: default blocking_check_fail_open to false Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eue is configured (#14681) A zero queue_wait_timeout_millis makes an admitted request time out immediately instead of waiting for a worker slot, silently defeating the queue. Reject it in from_args when max_queued_requests > 0; a zero timeout remains valid when no queue is configured (a request never waits). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e capacity (#14679) max_concurrent_requests + max_queued_requests sizes the admission semaphore, and tokio's Semaphore panics when constructed with more than MAX_PERMITS. Validate the sum in from_args (via checked_add + MAX_PERMITS bound) and return a clean ConfigError instead of crashing at startup on an oversized or overflowing config. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jsii-pacmak/codemaker 1.138.0 (resolved unpinned at CI time via cdk8s-cli) generate bindings that import jsii._type_checking.cached_type_hints, which requires the jsii 1.138.0 Python runtime. The locked 1.134.0 runtime fails with an ImportError during cdk8s synth in every system test run. (cherry picked from commit 0e43ee6) Co-authored-by: Matan Lior <matan.l@starkware.co> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* workspace: upgrade cairo compiler to v2.19.2 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * starknet_api,starknet_os_flow_tests: bump SierraVersion::LATEST to 1.9.1 and regen fixtures for cairo 2.19.2 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * central_systest_blobs: update cende operator/fee-token addresses and blob fixtures for cairo 2.19.2 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * central_systest_blobs: bump cende blob generation to 49 (re-uploaded blob for cairo 2.19.2) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * apollo_integration_tests: regenerate proof-flow fixtures for cairo 2.19.2 (sierra 1.9.1) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…id (#14165) * starknet_transaction_prover: per-request structured log with request-id Adds `RequestLogLayer`, the outermost middleware that emits one `event="http_request"` log line per request (request_id, method, path, status, latency_ms) and echoes the id on the response. The id is accepted from `x-request-id` when it is a short printable-ASCII token, otherwise a UUID v4 is generated; hostile inputs are dropped to prevent header smuggling and log-field explosion. No request body bytes are inspected (transaction calldata is private user data). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * starknet_transaction_prover: skip health-probe request logs, tighten request-id plumbing Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Covers state_maps_to_committer_state_diff (empty / nonces / storage / compiled class hashes) and validate_virtual_os_state_diff (valid storage, valid nonce, and rejection of storage deletion / contract deployment / contract declaration).
…for decapsulated content (#14222) * starknet_transaction_prover,tower_ohttp: OHTTP-unlinkable request-id for decapsulated content Tags downstream content logs with a request-id via a new `RequestSpanLayer` placed below the OHTTP layer. For plaintext it reuses the envelope id from `RequestLogLayer`; for an OHTTP-decapsulated request (marked with a new `tower_ohttp::Decapsulated` extension) it mints a FRESH UUID and discards any client-supplied inner id. The fresh inner id is never echoed back, so the relay-visible envelope id and the gateway's content-log id cannot be joined — preserving OHTTP unlinkability while still giving every request's downstream logs a correlatable id. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * starknet_transaction_prover,tower_ohttp: strip inner x-request-id at decapsulation Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…#14742) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
#14689) (#14760) Heights were resolved to "current epoch + 1" for up to MIN_EPOCH_LENGTH blocks past the current epoch's end. When epochs are shorter than MIN_EPOCH_LENGTH, this attributed heights of later epochs to a stale epoch ID, so epoch-gated committee changes took effect at a different height on each node. Bound the window by min(MIN_EPOCH_LENGTH, epoch_length) so the resolved epoch is always exact; behavior is unchanged for epochs of at least MIN_EPOCH_LENGTH. (cherry picked from commit 86e00e8) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ient) (#14519) (#14748) The mempool fetches dynamic config from the config manager on every request and `.expect()`s the result. If the config manager client were remote, a transient network failure would panic and crash the mempool (security report H-5). The config manager is a local infrastructure component co-located with its consumers, so reject any execution mode that would build a remote client (`Remote` / `LocalExecutionWithRemoteEnabled`) at config validation time, turning a deep startup panic into an early, descriptive error and guaranteeing the client is always an in-process channel. (cherry picked from commit 3c4beae) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ync deadlock (#14666) (#14750) A crash between renaming the staged class directory into place and committing the existence marker leaves an orphaned, non-empty persistent directory. On the next attempt std::fs::rename fails with ENOTEMPTY, which permanently wedges sync on that class. Remove a pre-existing persistent directory before the rename so the write self-heals; the directory is content-addressed by class hash, so it holds the same class. Covers both the regular and deprecated class write paths. (cherry picked from commit 7b2c35e) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ensus_block_number_stuck (#14705) (#14752) consensus_block_number_stuck paged p1 on a healthy Mainnet node-0: at Grafana eval time increase(consensus_block_number[120s]) intermittently returned no data (cross-region GMP recency on the lone us-west1 node), and `or vector(0)` turned that empty result into a hard 0 < 1 -> false page. Fall back to vector(1) instead: an absent/late series no longer reads as a halt, while a real halt keeps the gauge present (increase yields a present 0) and still fires immediately. A dead pod stays covered by pod_state_not_ready / pod_state_crashloopbackoff. (cherry picked from commit 72ced2b) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…14500) (#14757) Future-height votes were cached with no count limit, no committee-membership check, and no signature verification (the voter is attacker-controlled), so a peer could flood the node with forged votes for future heights and grow future_votes without bound until OOM (H-19). Cap the per-height future-vote cache statically at MAX_COMMITTEE_SIZE * NUM_VOTE_TYPES * (future_height_round_limit + 1) -- an upper bound on what an honest committee could produce. Using the static MAX_COMMITTEE_SIZE (added to apollo_staking) rather than the live committee size keeps the cap always active, including on syncing nodes that never run a height locally, so future votes are still cached (crucial for catch-up) but bounded. Votes beyond the cap are dropped and logged. (cherry picked from commit c52fd6d) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…batcher first (#14698) (#14761) The mock staking contract derives the current epoch from the chain's latest block number. It read this solely from state sync, which is a downstream reader that can lag the commit tip significantly. Because committee resolution can only look ahead MIN_EPOCH_LENGTH (150) blocks past the epoch boundary implied by that height, a state-sync lag approaching ~150 blocks pushes the consensus height beyond the resolvable window: get_committee returns InvalidHeight, and consensus falls back to waiting for sync instead of producing blocks. Read the height from the batcher first (its storage marker tracks the commit tip), falling back to state sync on error, mirroring get_block_hash_with_fallback. The batcher get_height marker is the next-to-build height, so the latest committed block is one below it. Epoch math is unchanged; only the height source moves closer to the tip. This also aligns the mock with CairoStakingContract, which already reads epoch data via the batcher. (cherry picked from commit 6cfff03) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…commits[0] index (#14605) (#14758) Both run_consensus and run_height derived the decided round from decision.precommits[0]/.first(), a latent panic if a Decision ever carried an empty precommit set (unreachable today, but a fragile invariant). Add an explicit `round` field to `Decision`, populated in upon_decision where the round is already in scope, and read it at both call sites. This removes the raw index and the sibling expect, making the empty-precommit case irrelevant to round derivation. (cherry picked from commit 68863a6) Co-authored-by: asaf-sw <asaf@starkware.co> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…14047) Adds unit tests for VirtualSnosProver input validation: pending block rejection, DeployAccount rejection, proof/proof_facts field rejection, non-zero fee field rejection (with the validation knob respected when disabled), and a happy-path test that asserts a valid invoke reaches the runner. Adds two test runners — UnreachableRunner (panics on invocation, for tests where validation must reject the input) and FailingRunner (returns an error, for tests that must verify the runner is reached without needing a real node).
…ce hits configured minimum (#14773) Fire a P3 (all envs) alert when the accepted L2 gas price is clamped at the configured minimum (min_l2_gas_price_per_height, or the versioned-constants min_gas_price fallback) for a sustained 2m window. Emit a new consensus_l2_gas_price_at_minimum gauge where consensus_l2_gas_price is already set, and have the alert read that signal rather than a literal Grafana threshold — a literal would be wrong on Mainnet (configured min = 15e9, not the 8e9 fallback) and would rot when the versioned-constants min changes. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#14855) * apollo_dashboard: tolerate L1 pod spot eviction in L1 provider alerts The batcher (l1_events) and consensus (l1_gas_price) reach providers hosted in the L1 service pod over HTTP. In distributed deployments that pod runs on a spot node pool and is periodically evicted; a normal eviction + reschedule + L1-provider catch-up recovers within a few minutes, but the transient errors it produces were tripping the paging alerts on routine churn. Require the error condition to hold continuously past the expected bootup window (for=3m over a short 1m increase window) so only a sustained L1 outage pages. Escalate batcher_l1_events_provider_errors to p2 (resolving the inline TODO); consensus_l1_gas_price_provider_failure keeps p4. The p5 _once signal is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * apollo_dashboard: tighten L1 provider alert docs and extract error-window const Address review: use a tighter doc comment for L1_POD_BOOTUP_TOLERANCE and pull the shared "1m" sampling window into L1_POD_ERROR_WINDOW, dropping the redundant inline comments. No change to generated alert JSON (values are identical). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * apollo_dashboard: use sum_increase query helper for L1 provider alert exprs Replace the hand-written sum(increase(...)) in the batcher l1_events and consensus l1_gas_price alerts with the shared query_builder::sum_increase helper, matching the existing l1_gas_prices.rs usage. No change to generated alert JSON. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#14841) Add a runtime safety net in initialize_execution_context_with_runner_mode that rejects a Cairo 1 entry point whose builtins are not an ordered subsequence of the supported set (CAIRO1_SUPPORTED_BUILTINS, mirroring the OS SelectableBuiltins struct), right before they are handed to the Cairo runner. The Sierra compiler already enforces this at compile time; this check is a defensive guard at the point of use, rather than at declare/add_class time as in #14801. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bumps the Rust cairo-lang-* crates and the Sierra compiler binary version from 2.19.3 to 2.19.4. The bump moves the Sierra version from 1.9.2 to 1.9.3, cascading into Cairo1 class hashes and their downstream fixtures: starknet_os_flow_tests fuzz-deployment addresses and hint-coverage fixtures, the proof-flow genesis global root and STRK fee-token address, the cende blob regression (operator/fee-token addresses, chain_info/preconfirmed_block, GCS blob generation), and the apollo_integration_tests proof-flow fixtures. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tx idle alerts (#14876) The three idle alerts built by `build_idle_alert` (gateway_add_tx_idle_p2p_rpc, mempool_add_tx_idle_p2p_rpc, http_server_no_successful_transactions) used `sum(increase(<metric>[Ws])) or vector(0)` with a `< 0.1` threshold. A transient metric scrape/ingestion gap makes `increase` return empty, and `or vector(0)` turns that into a hard 0 that trips the threshold and false-pages even while tx ingestion is healthy (confirmed on apollo-sepolia-alpha-3 on 2026-07-22 ~13:50Z: ~3-min gap in gateway_transactions_received while RPC txs were still being recorded and the pod stayed up). Fall back to `vector(1)` instead: an unscrapeable series reads as 1 (>= the 0.1 threshold) so it no longer pages, while a real idle keeps the counter present so `increase` yields a present 0 and still fires. Same fix already shipped for consensus_block_number_stuck (#14705, backport #14752) in block_production_halt.rs; this propagates it to the tps.rs idle alerts. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Src Dst crates/apollo_batcher/src/batcher.rs |
PR SummaryHigh Risk Overview Batcher / consensus: Block building now uses a separate Execution & mempool: Blockifier validates Cairo 1 entry-point builtins against a canonical ordered list and records block-full bouncer metrics once per block. The mempool clears gap accounts from Transaction prover: HTTP/TLS stacks share a Dashboard / config: L1-provider-related alerts use shorter error windows and 3m pending tolerance; some noisy rules are dropped or adjusted (e.g. idle tx metrics fall back to Reviewed by Cursor Bugbot for commit 3e63610. Bugbot is set up for automated code reviews on this repo. Configure here. |
|
Artifacts upload workflows: |
ron-starkware
left a comment
There was a problem hiding this comment.
@ron-starkware reviewed 71 files and all commit messages.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on ron-starkware).
Resolve the 20 conflicts from merging main-v0.14.3 into main, plus two skews the conflict markers did not surface: - proof.bin is binary, so the merge picked main's version with no marker while its companion proof_facts.json stayed conflicted. Both are now regenerated together. - tower_ohttp moved its inline tests to a sibling layer_test.rs on main (#14559) while main-v0.14.3 added a test to the inline block (#14222); taking either side alone drops one of the two changes. The merged genesis state differs from both sides, so the proof-flow fixtures were regenerated rather than taken from either branch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ron-starkware
left a comment
There was a problem hiding this comment.
Per-conflict resolution notes for the fix_conflicts commit (f77122d). 20 textual conflicts across 13 files, plus 2 skews the conflict markers did not surface. Inline notes below explain each choice and tag the authors on both sides.
Two things worth a closer look from reviewers:
proof.binwas resolved silently. It is binary, so git tookmain's version with no marker while its companionproof_facts.jsonstayed conflicted.- The merged genesis state differs from both branches, so every genesis-derived fixture (fee token address, global root, 5 fuzz addresses, and the proof fixtures) had to be regenerated rather than picked from a side. The
proof_flow_fixtures_match_genesis_block_hashguard cannot be refreshed withUPDATE_EXPECT=1by design — it only passes once the proof is actually regenerated, which it now is.
Verification: cargo check --all-targets clean on all affected crates; tower_ohttp (16), apollo_dashboard (125), apollo_node_config (20), apollo_consensus (95), apollo_mempool (16), apollo_class_manager (15), apollo_batcher_config, and all 3 proof_flow_fixtures_verify tests pass.
Resolutions with no inline anchor
These took the main side, so they are net-unchanged against the PR base and GitHub has no diff line to attach a comment to. Notes here instead.
crates/apollo_class_manager/src/class_storage.rs
Conflict: both branches extracted a rename_to_persistent_dir helper for the same ENOTEMPTY fix, with different signatures.
main(@matanl-starkware #14666) added the orphaned-dir recovery, then @gkaempfer's #14668 refactored it to take a precomputedpersistent_dirand deletedget_persistent_dir_with_create.main-v0.14.3(#14750) only backported #14666, so its helper still takesclass_idand callsget_persistent_dir_with_create.
Resolution: took main. This is not a style preference — get_persistent_dir_with_create no longer exists anywhere in the merged file, so the v0.14.3 side would not compile. main's variant is also the better one: it renames optimistically and recovers only on DirectoryNotEmpty/AlreadyExists, avoiding the stat-then-rename TOCTOU window.
cc @matanl-starkware @gkaempfer
crates/apollo_consensus/src/manager_test.rs
Conflict: import list; main is the superset.
main(@matanl-starkware #14635/#14636) addedSKIPPED_PROPOSER_FAR_BEHINDon top of #14500'sConsensusCache/NUM_VOTE_TYPES.main-v0.14.3(#14757) only backported #14500.
Resolution: took main — it already contains v0.14.3's imports plus the far-behind ones.
crates/apollo_mempool/src/fifo_mempool_test.rs
Conflict: import list; main is the superset.
main(@ron-starkware #14724) addedBlockNumberalongsideinternal_invoke_tx.main-v0.14.3(#14755, backport of #14568) added onlyinternal_invoke_tx.
Resolution: took main.
…state The merged tree matches neither branch, so v0.14.3's preconfirmed_block.json was stale in two ways: StarknetVersion::LATEST is now 0.14.4 (main added the 0.14.4 versioned constants), and the fee/gas figures shifted. The balance storage entry needed v0.14.3's key with main's value - the original conflict had each branch changing a different one of those two fields. Regenerated via UPDATE_EXPECT=1, which also uploaded the matching blob file to GCS as generation 55 (additive; 54 is untouched). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ron-starkware
left a comment
There was a problem hiding this comment.
Follow-up: central_systest_blobs::test_make_data failed on the first CI run. Root cause is the same one that drove the proof-fixture regeneration — the merged tree equals neither branch, so any fixture taken from a side is stale. This was a fourth instance of it, and unlike the others it was invisible from the conflict markers. Fixed in 3e63610 and verified green in CI mode (not just under UPDATE_EXPECT).
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 3e63610. Configure here.
ron-starkware
left a comment
There was a problem hiding this comment.
@ron-starkware resolved 7 discussions.
Reviewable status: 57 of 73 files reviewed, 5 unresolved discussions (waiting on avi-starkware, dan-starkware, and matanl-starkware).
avi-starkware
left a comment
There was a problem hiding this comment.
@avi-starkware reviewed 3 files.
Reviewable status: 60 of 73 files reviewed, 4 unresolved discussions (waiting on matanl-starkware and ron-starkware).
matanl-starkware
left a comment
There was a problem hiding this comment.
@matanl-starkware reviewed 11 files and all commit messages.
Reviewable status: 71 of 73 files reviewed, 4 unresolved discussions (waiting on ron-starkware).
dan-starkware
left a comment
There was a problem hiding this comment.
@dan-starkware reviewed 2 files.
Reviewable status: all files reviewed, 4 unresolved discussions (waiting on ron-starkware).
matanl-starkware
left a comment
There was a problem hiding this comment.
@matanl-starkware resolved 4 discussions.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on ron-starkware).
|
Security scan complete — no issues detected. Generated by Claude Code |

No description provided.