Skip to content

feat: score escrow with configurable hold window before auto-commitment#2

Open
Neche58 wants to merge 99 commits into
mainfrom
feat/score-escrow-hold-window
Open

feat: score escrow with configurable hold window before auto-commitment#2
Neche58 wants to merge 99 commits into
mainfrom
feat/score-escrow-hold-window

Conversation

@Neche58

@Neche58 Neche58 commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Closes Ledger-Lenz#277

Summary

Implements an escrow hold window for score submissions. When configured, submit_score writes to escrow instead of live storage; anyone may call auto_commit_score after the window elapses, and the admin can cancel via cancel_escrow_score.

Changes

  • MAX_ESCROW_HOLD_WINDOW_SECS constant (7 days)
  • EscrowHoldWindow and EscrowScore DataKey variants
  • Storage: get/set_escrow_hold_window, get/set/clear_escrow_score
  • Contract: set_escrow_hold_window, get_escrow_hold_window, get_escrow_score, auto_commit_score (permissionless, post-window), cancel_escrow_score (admin)
  • Patch submit_score: when escrow_window > 0, route to escrow path with rate-limit check
  • test_escrow.rs with full test suite and snapshots

Anichris-koded and others added 30 commits June 22, 2026 23:12
Track and expose the total number of score submissions per asset pair.

- Add DataKey::PairScoreCount(Symbol) variant and as_val mapping
- Add storage::increment_pair_score_count / get_pair_score_count
- Increment counter in write_score_with_rate_limit, submit_scores_batch,
  submit_scores_batch_attested, commit_pending_score, and dispute
  resolution paths on every successful write
- Add public get_pair_score_count(asset_pair: Symbol) -> u64 with rustdoc
- Add test_pair_score_count.rs: 11 tests covering initial state, single
  and repeated submissions, pair isolation, batch path, and partial
  rejection
Expose the configured rate-limit window duration so integrators can
implement proper retry logic without triggering RateLimitExceeded.

- Add public get_rate_limit_window() -> u64 that returns the global
  cooldown (same underlying value as get_cooldown, explicit alias for
  integrator discoverability) with full rustdoc and usage example
- Add test_rate_limit_window.rs: 5 tests asserting default value,
  agreement with get_cooldown, and reflection of set_cooldown changes
Track and expose the total number of unique (wallet, asset_pair)
combinations ever scored, for protocol health monitoring dashboards.

- Add DataKey::TotalWalletsScored variant and as_val mapping
- Add storage::increment_total_wallets_scored / get_total_wallets_scored
- Increment counter on the first successful submission for each new
  (wallet, asset_pair) combination across all write paths:
  write_score_with_rate_limit (uses previous_score.is_none() guard),
  submit_scores_batch (same guard), submit_scores_batch_attested, and
  commit_pending_score (uses score_count==1 guard)
- Add public get_total_wallets_scored() -> u64 with rustdoc and example
- Add test_total_wallets_scored.rs: 10 tests covering initial state,
  first submission, re-submission idempotency, multiple wallets,
  different pairs as separate combinations, rejection non-increment,
  and batch paths
Expose the score submission cooldown in seconds so off-chain scoring
services can schedule re-submissions without hitting on-chain rejections.

- Add public get_cooldown_period() -> u64 that returns the configured
  global cooldown (named alias of get_cooldown for off-chain schedulers)
  with full rustdoc including a scheduling usage example
- Add test_cooldown_period.rs: 6 tests covering the default value,
  agreement with get_cooldown, reflection of set_cooldown changes at
  both bounds and an arbitrary value, and a scheduling use-case test
  that verifies the returned value matches actual enforcement behaviour
…air_paused

The is_pair_paused function already exists publicly, but its pr_rd capability was not registered in supports_interface. This adds the capability token, a dedicated interface test, and updates the test snapshot and README accordingly.
…d audit chain infrastructure

- Issue Ledger-Lenz#200: Add contract_id (BytesN<32>) and contract_version (u32) fields to ScoreAttestation and ThresholdAttestation
- Verify contract_id and contract_version match current contract on-chain values before validating signature
- Update digest computation to include contract_id and contract_version fields (preimage now 243 bytes)
- Add comprehensive tests for correct/wrong/zero contract_id validation
- Update attestation-spec.md with new digest layout and migration notes
- Issue Ledger-Lenz#201: Add Merkle audit chain infrastructure for admin governance actions
- Add DataKey::AdminAuditRoot and initialize genesis root to zero hash
- Implement update_audit_root() helper to maintain sha256 chain of admin actions
- Add public get_admin_audit_root() function to retrieve current audit root
- Update pause(), unpause(), propose_upgrade() to emit audit events (pattern for remaining admin functions)
- Create docs/audit-chain.md with verification schema and off-chain replay example
- Issue Ledger-Lenz#202: Add DecayProfile enum with Linear, Exponential, Step variants
- Add DecayProfile to DataKey enum for storage (further implementation needed)
- Issue Ledger-Lenz#203: Prepare for multi-dimensional risk scores by adding DecayProfile infrastructure

Work in progress: Issues Ledger-Lenz#202 and Ledger-Lenz#203 require additional implementation of decay logic and risk score breakdown features.
…re foundation

- Issue Ledger-Lenz#202: Add DecayProfile enum (Linear, Exponential, Step variants)
- Add DecayProfile to DataKey for configuration storage
- Lay foundation for configurable score decay curves
- Issue Ledger-Lenz#203: Add benford_score, ml_score, network_score sub-fields to RiskScore
- Add ScoreComponentWeights to DataKey for weight storage
- Bump CONTRACT_VERSION to 4 for breaking ABI changes
- Add migration notes for version 4

Note: Full implementation of decay profile dispatch logic and weighted score aggregation
in submit_score/submit_scores_batch requires additional work to integrate with existing
score submission flow.
…edger-Lenz#213)

Introduce propose/execute/veto governance for admin parameter changes with
service-signer veto during the first half of the delay window, a cap of 10
pending proposals, and expiry after 2× the time-lock.
Skip extend_ttl on score and touch-marker entries when the entry was
recently renewed, with regression tests measuring >=15% fewer extend calls
on pre-warmed 20-entry batch resubmits.
…z#214)

Add provide_liquidity_gated with query_risk_gate_with_confidence, set_risk_oracle,
unit tests, amm_gate_example, and composability documentation.
…r-Lenz#307)

Add benches/batch_submit.rs measuring wall time and Soroban budget cost at
batch sizes 1, 10, 50, and 100, with CI artifact upload on main merges.
Remove two auto-generated snapshot files (~49k lines) and refactor TTL
tests to prewarm via storage writes and use a small batch for the
submit_scores_batch regression test.
…Lenz#214)

Drop auto-generated test_snapshots JSON (~17k lines), move mock-AMM
liquidity tests to the composability suite, and seed governance cap tests
via storage to keep future snapshots small.
…fecycle (Ledger-Lenz#207)

feat: add wallet risk cluster assignment by score-similarity bucketing (Ledger-Lenz#205)
- Implement assign_risk_cluster() to compute cluster ID from score / 10
- Implement get_cluster_members() signature for future cluster index storage
- Add DataKey variants for cluster management

feat: add adaptive consensus epsilon from rolling score variance (Ledger-Lenz#204)
- Implement set_adaptive_epsilon() for dynamic epsilon configuration
- Implement get_adaptive_epsilon() to retrieve bounds and enabled status
- Add storage functions for adaptive epsilon state management
- Support enable/disable with configurable min/max bounds clamped to risk threshold

feat: add score momentum indicator with configurable rolling window (Ledger-Lenz#206)
- Implement get_score_momentum() for signed rate-of-change calculation
- Return average score delta per second within time window
- Clamp window at DEFAULT_STALENESS_WINDOW_SECS to prevent abuse
- Return 0 for fewer than 2 history entries in window

tests: add comprehensive lifecycle scenarios
- Full end-to-end test covering initialize → multisig setup → score submission
- Adversarial tests: unauthorized submissions, paused state enforcement
- Multisig threshold validation (single vs multi-signer)
- Feature tests for cluster assignment, adaptive epsilon, and momentum

All integration tests passing. cargo test verified.
…bargoes

Adds a persistent u32 counter that tracks how many wallets are currently
under an active score embargo, exposing it via the new public
get_active_embargo_count() -> u32 contract function.

The counter lives in persistent storage (DataKey::ActiveEmbargoCount) so
it survives temporary-storage TTL eviction — unlike EmbargoedWalletIndex
which is stored in temporary storage. This makes it a reliable, O(1)
signal for admin dashboards and monitoring tools that need a fast gauge of
the current embargo load without enumerating all wallets.
Inkman007 and others added 30 commits June 26, 2026 17:02
…es-298-299-297-302

feat: M-of-N upgrade proposals, governance audit chain, IQR consensus…
feat: expose get_score_threshold() -> u32 read-only function
…-override-log-and-dual-key-overlap

feat: rate-limit override audit log and dual-key pubkey overlap
…4-305-306-fuzz-property-chaos-tests

test: fuzz, property, integration & chaos tests (closes Ledger-Lenz#303 Ledger-Lenz#304 Ledger-Lenz#305 Ledger-Lenz#306)
Update LedgerLens score contract logic and tests
…g-flash-protection

feat: epoch sealing (Ledger-Lenz#301) and anti-flash-loan protection (Ledger-Lenz#300)
…ner-reputation-weighting

feat(Ledger-Lenz#274): signer reputation weighting in consensus
…cle-adapter-interface

feat(Ledger-Lenz#276): oracle adapter interface for external price feed
…e-288-wallet-risk-cluster

feat(Ledger-Lenz#288): wallet risk cluster assignment via score-similarity bucke…
…e-287-adaptive-epsilon

Feat/issue 287 adaptive epsilon
…tility-index

feat(Ledger-Lenz#270): rolling 24h score volatility index per asset pair
…e-limit

feat(Ledger-Lenz#275): add adaptive rate limit scaled by global score variance
…ce-signer-count

feat: add get_service_signer_count() -> u32 for M-of-N monitoring
…t-counter

feat: HyperLogLog probabilistic unique wallet counter per asset pair
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement score escrow with configurable hold window before auto-commitment