chore(release): promote rc-2026.6.2#138
Closed
jacderida wants to merge 25 commits into
Closed
Conversation
A disk-full node previously ran full payment verification — ML-DSA pool checks, a Kademlia closeness lookup, and an on-chain Arbitrum RPC — on every PUT before discovering at storage time that it had no space, only to reject the chunk. At fleet scale this wasted RPC/network load and delayed the client's fallback to another peer (V2-411). Add a cheap disk-space pre-check that runs immediately after the already-exists check and before payment verification: - Expose `LmdbStorage::check_capacity()` wrapping the existing cached `check_disk_space_cached()` (passing results only, so freed space is still detected promptly; effectively free per-PUT). - In `handle_put_inner`, call it before `verify_payment`; on insufficient space, emit an info-level reject log (target `ant_node::storage::disk_precheck`) and return the existing `ProtocolError::StorageFailed` early, preserving client behaviour. - Keep the store-path check as defence-in-depth (pre-check↔store race, replication writes). The reject log is greppable for testnet verification. Backwards compatible: no wire/response-variant change. A dedicated OutOfCapacity/TryElsewhere response is left to V2-469. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… fresh offers DEV-02 testnet verification of the PUT-handler pre-check (the previous commit) showed full nodes still doing wasted payment verification on the replication push path: ~491 "EVM payment verified" log lines on the two full VMs, each followed by "Failed to store fetched record ...: Insufficient disk space". That work runs in handle_fresh_offer, which is not covered by the handle_put_inner reordering. Mirror V2-411 into the fresh-offer path: call LmdbStorage::check_capacity() immediately after the responsibility check and before verify_payment. On insufficient space, emit the same info-level reject log (target ant_node::storage::disk_precheck, with a replication-specific message) and return a Rejected response, instead of verifying a payment for a record the node can never store. The store-path check inside put() remains as defence-in-depth. The pull/fetch path (FetchResponse store) does no payment verification, so it is left unchanged. No behavioural change for nodes with free space. Verification: re-run the same small testnet and confirm the full hosts' "EVM payment verified" volume drops while disk_precheck reject logs cover the replication path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Narrow `LmdbStorage::check_capacity` from `pub` to `pub(crate)`: it is only
used in-crate (PUT handler + replication), so it should not widen the lib API.
- Drop the redundant "Storage error: " prefix from the replication rejection
reason: `Error::Storage` already renders as "storage error: ...", so
`format!("Storage error: {e}")` produced "Storage error: storage error: ...".
Use the error's own message instead, here and on the adjacent pre-existing
store-failure branch for consistency.
- Reword the PUT pre-check comment: the cached check is free per-PUT on a
healthy node, but a disk-full node re-runs a cheap `available_space` syscall
each PUT (still negligible next to the verification it avoids).
No behavioural change. cargo fmt/clippy/doc clean; replication 233/233,
storage 30/30 tests pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix: disk-space pre-check before payment verification on full nodes
BREAKING CHANGE: removes ant-node bootstrap-cache config, CLI flags, and manager integration while updating ant-node to the ant-protocol and saorsa-core bootstrap-cache removal branches.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat!: depend on bootstrap-cache removal chain
Prune deletion required every peer in the current close group to prove possession, but fresh replication is fire-and-forget and uploads/repair only guarantee QUORUM_THRESHOLD placement (4 of 7). One lagging peer vetoed the prune forever, leaving prod nodes unable to free disk while audit-proof WARNs accumulated. A record that is out of the node's closest 7 now prunes once all but one of the current close group (6 of 7 at production parameters) prove they hold the exact bytes. This keeps a single absent peer from blocking deletion forever while still requiring near-full placement before the extra copy is dropped. Groups of one or two peers still require every proof. The mature-repair-proof precondition follows the same rule: a never-synced close-group peer reduces the audit pool instead of vetoing the prune, and only hinted peers are ever audited. PaidForList entry pruning gets its own remote gate: an out-of-range entry was previously removed on local state alone once the hysteresis elapsed; it is now retained until three quarters of the current paid close group (15 of 20 at production parameters) confirm the key in their own paid lists. Confirmations are revalidated against the current paid close group after the network round, the scan rotates through a dedicated cursor so capped passes cannot starve later entries, and chunk pruning checks only chunk possession while paid pruning checks only paid-list confirmations. Also split the failed-proof WARN into key-absent vs digest-mismatch so the two failure modes can be told apart in production logs.
Verify paid single-node quotes from 1..=CLOSE_GROUP_SIZE supplied quotes while preserving the existing 0x01 proof format and 3x payment requirement. Run direct client PUTs and fresh chunk replication through the full ClientPut check set, including local close-group receiver membership. Run fresh paid-list admission through the same live payment checks with K-wide receiver membership, and keep verified-payment cache entries scoped by verification strength.
fix(pruning): tolerate one lagging peer in the prune proof gate
Move receiver placement checks out of PaymentVerifier so proof verification only validates payment contents and paid-quote issuer locality. Direct client PUTs now check local close-group storage responsibility before payment verification, while fresh replication and paid-list notification paths keep their pre-verification admission gates. Paid quote issuers are now checked against the configured close group instead of K closest peers.
…pair-hint-min-age # Conflicts: # src/replication/pruning.rs
…payment-proofs feat(payment): accept flexible single-node proof bundles
fix(replication): require aged repair hints before audits
fix(replication): widen local storage admission range
There was a problem hiding this comment.
Pull request overview
This PR bumps ant-node to release 0.12.1 and updates dependencies/lockfile, but it also contains substantial behavior changes across storage admission, pruning, and payment verification that materially affect runtime semantics.
Changes:
- Promote version to
0.12.1, updateant-protocol/saorsa-coreversions, and regenerateCargo.lock. - Introduce storage-admission margin + early disk-capacity pre-checks, and wire P2P into
AntProtocolfor PUT responsibility/payment live-DHT checks. - Revise replication pruning + repair-proof maturity semantics, and overhaul payment verification contexts/caching behavior (incl. paid-list admission).
Reviewed changes
Copilot reviewed 24 out of 25 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/e2e/testnet.rs | Update E2E wiring to attach P2P to AntProtocol; propagate close-group size into payment verifier config. |
| tests/e2e/replication.rs | Expand replication/pruning E2E coverage (proof thresholds, paid-list pruning confirmations, content mismatch rejection). |
| tests/e2e/merkle_payment.rs | Route attack test traffic to the locally responsible receiver; import CLOSE_GROUP_SIZE. |
| tests/e2e/data_types/chunk.rs | Ensure PaymentVerifierConfig includes close_group_size in test setup. |
| src/storage/lmdb.rs | Add check_capacity() wrapper for cached disk-space pre-checks. |
| src/storage/handler.rs | Add P2P attachment + direct PUT storage-admission validation and disk pre-check before payment verification. |
| src/replication/types.rs | Add wall-clock minimum age to repair proofs; test-only timestamp injection. |
| src/replication/quorum.rs | Derive Default for VerificationTargets to support new pruning verification flows. |
| src/replication/pruning.rs | Implement all-but-one prune proof threshold; add paid-list remote confirmation gating + per-pass budgets/cursoring. |
| src/replication/paid_list.rs | Add paid-prune cursor to rotate expired-entry verification windows; add tests. |
| src/replication/mod.rs | Tighten fresh-offer/paid-notify admission: content-address validation, storage-admission width, disk pre-check, context changes. |
| src/replication/config.rs | Add STORAGE_ADMISSION_MARGIN, storage_admission_width, and REPAIR_HINT_MIN_AGE. |
| src/replication/audit.rs | Pass Instant into repair-proof maturity checks; add “fresh hint” test coverage. |
| src/replication/admission.rs | Generalize responsibility width and apply storage-admission width for replica hint admission. |
| src/payment/verifier.rs | Replace replication context with PaidListAdmission; enforce issuer close-group + paid-quote floor; revise cache semantics. |
| src/payment/quote.rs | Update docs/comments to match paid-quote price-floor semantics. |
| src/payment/cache.rs | Track verification level (PaidList vs ClientPut) rather than a boolean flag; add tests. |
| src/node.rs | Wire P2P into AntProtocol (instead of directly into verifier) and remove bootstrap-cache manager integration. |
| src/lib.rs | Stop exporting removed bootstrap-cache config types. |
| src/devnet.rs | Update devnet wiring to attach P2P to AntProtocol; propagate close-group size into payment verifier config. |
| src/config.rs | Remove bootstrap-cache config and refactor bootstrap peer discovery helper. |
| src/bin/ant-node/cli.rs | Remove bootstrap-cache CLI flags/config plumbing. |
| docs/DESIGN.md | Remove bootstrap manager references in design doc snippet. |
| Cargo.toml | Bump crate version and dependency versions. |
| Cargo.lock | Regenerated lockfile for updated versions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
521
to
533
| pub fn discover() -> Option<(Self, PathBuf)> { | ||
| let candidates = Self::search_paths(); | ||
| for path in candidates { | ||
| if path.is_file() { | ||
| match Self::from_file(&path) { | ||
| Ok(config) if !config.peers.is_empty() => return Some((config, path)), | ||
| Ok(_) => {} | ||
| Err(err) => { | ||
| crate::logging::warn!( | ||
| "Failed to load bootstrap peers from {}: {err}", | ||
| path.display(), | ||
| ); | ||
| } | ||
| } | ||
| if let Ok(env_path) = std::env::var(BOOTSTRAP_PEERS_ENV) { | ||
| return Self::load_non_empty_candidate(PathBuf::from(env_path)); | ||
| } | ||
|
|
||
| for path in Self::search_paths() { | ||
| if let Some(discovered) = Self::load_non_empty_candidate(path) { | ||
| return Some(discovered); | ||
| } | ||
| } | ||
|
|
||
| None | ||
| } |
Comment on lines
+177
to
191
| fn insert_with_level(&self, xorname: XorName, level: VerificationLevel) { | ||
| let added = { | ||
| let mut inner = self.inner.lock(); | ||
| // `get_mut` refreshes LRU recency for existing entries of either kind. | ||
| if inner.get_mut(&xorname).is_none() { | ||
| inner.put(xorname, false); | ||
| true | ||
| } else { | ||
| if inner.get(&xorname).is_some() { | ||
| if let Some(existing) = inner.get_mut(&xorname) { | ||
| if !existing.satisfies(level) { | ||
| *existing = level; | ||
| } | ||
| } | ||
| false | ||
| } else { | ||
| inner.put(xorname, level); | ||
| true | ||
| } |
Comment on lines
1
to
4
| [package] | ||
| name = "ant-node" | ||
| version = "0.12.0" | ||
| version = "0.12.1" | ||
| edition = "2021" |
Collaborator
Author
|
Closing: reverting RC branch to RC state (0.12.1-rc.1) to build RC binaries for testnet validation before release. Will re-open the promotion PR after the testnet passes. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Promotes
rc-2026.6.2to release version(s): 0.12.1.-rc.*from[package].versionCargo.lockOnce merged, the release tag will be pushed to fire the publish workflow.