Skip to content

test(earn-quest): property tests for incremental user-stat counters - #2170

Merged
RUKAYAT-CODER merged 2 commits into
EarnQuestOne:mainfrom
walexjnr:feat/2153-incremental-user-stats
Aug 19, 2026
Merged

test(earn-quest): property tests for incremental user-stat counters#2170
RUKAYAT-CODER merged 2 commits into
EarnQuestOne:mainfrom
walexjnr:feat/2153-incremental-user-stats

Conversation

@walexjnr

Copy link
Copy Markdown
Contributor

Closes #2153

Summary

get_user_stats returns a user's aggregate stats from the incrementally-maintained UserCore counters (xp, level, quests_completed) — award_xp updates them in place on the completion path, so get_user_stats is an O(1) storage read (storage::get_user_stats_or_default) rather than a scan-and-recompute over the user's award history. Read cost and gas therefore do not grow with history.

This PR locks in the invariant that optimisation depends on and documents it.

Changes

  • test_incremental_stats suite — a property/fuzz test that, over thousands of randomised award sequences, asserts the incrementally-folded counters always equal a full recompute from the complete award history (apply_incremental(awards) == full_recompute(awards)), plus boundary checks that the stored level matches calculate_level(xp) at every threshold. The tests are pure (no storage/ledger/contract calls), so they add no gas to the hot path and can never regress the gas benchmarks.
  • Documentation — a # Performance (#2153) note on reputation::get_user_stats making the O(1) incremental guarantee explicit and pointing at the property suite.

Acceptance criteria

  • Incremental counters are read directly in get_user_stats (no per-call recompute) — already the case; now proven and documented.
  • New property/fuzz test demonstrates the incremental counters always equal a full recompute.
  • No regression / no gas impact (test-only + doc change).
  • Change is documented.

…arnQuestOne#2153)

get_user_stats reads the incrementally-maintained UserCore counters (updated
in place by award_xp on the completion path) as an O(1) storage lookup rather
than scanning and recomputing over a user's award history.

Add a property/fuzz suite (test_incremental_stats) that proves the invariant
this relies on: for any sequence of XP awards, the incrementally-folded
counters (xp, level, quests_completed) always equal a full recompute from the
complete history. The tests are pure (no storage/ledger), so they add no gas
to the hot path. Document the O(1) incremental guarantee on get_user_stats.
… no Vec)

The earn-quest contract is `#![no_std]`, so `std::vec::Vec` is not in scope.
Generate the fuzzed award sequences into a fixed-size `[u64; 64]` buffer and
slice it, keeping the property test dependency-free and no_std-compatible.
@RUKAYAT-CODER
RUKAYAT-CODER merged commit 61d291f into EarnQuestOne:main Aug 19, 2026
3 checks passed
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.

Maintain incremental user-stat counters instead of recomputing in get_user_stats

2 participants