feat: HyperLogLog probabilistic unique wallet counter per asset pair#1
Open
Neche58 wants to merge 90 commits into
Open
feat: HyperLogLog probabilistic unique wallet counter per asset pair#1Neche58 wants to merge 90 commits into
Neche58 wants to merge 90 commits into
Conversation
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.
…nd mermaid flowchart (Ledger-Lenz#313)
…nd formula blocks (Ledger-Lenz#315)
…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.
Clients need to know the valid score floor to prevent submitting out-of-range values without guessing or hard-coding the magic number. - Add MIN_SCORE = 0 and MAX_SCORE = 100 named constants to constants.rs so the valid score range is defined in one authoritative place. - Implement get_min_score(_env: Env) -> u32 in the contract, returning constants::MIN_SCORE. Read-only, callable by any account or contract without authorization. - Add rustdoc with a # Examples block mirroring the pattern used by adjacent getters (get_historical_max_score, get_score_velocity_cap). - Add test_get_min_score_returns_zero unit test.
Security & Scalability Enhancements for Ledgerlens Score Contract
…ount feat: add get_active_embargo_count() persistent counter for active em…
feat: expose get_min_score() -> u32 read-only function
Feat/get max score
…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
…-query feat(Ledger-Lenz#281): fee-per-query on query_risk_gate
…nt-checker Feat/invariant checker
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.
Closes Ledger-Lenz#279
Summary
Implements an on-chain HyperLogLog sketch per asset pair to estimate unique wallets scored, without storing the full wallet list.
Changes
HllSketchstruct +DataKeyvariants (HllSketch,HllPrecision)HLL_MIN_PRECISION(4),HLL_MAX_PRECISION(16),HLL_DEFAULT_PRECISION(10)hll_update,hll_estimate,get/set_hll_precision,get/set_hll_sketchset_hll_precision,get_hll_precision,estimate_unique_walletssubmit_score: updates sketch on first wallet observation per pairtest_hll.rswith full test suite and snapshots