๐๏ธ Storage Architecture
Storage is the foundation of pallet-xp.
It defines how XP identities persist, how reputation evolves, how constraints are enforced, and how lifecycle rules remain safe across runtime execution.
Unlike simple balance systems, XP storage tracks:
- identity ownership
- behavioral progression
- reputation state
- lock and reserve constraints
- liveness and reaping state
- protocol configuration
This makes storage part of the protocol logic, not just passive persistence.
Storage Philosophyโ
XP storage is designed around one principle:
๐ง Store behavior, not just balances
Traditional token systems mainly store balances.
pallet-xp stores:
- who owns the identity
- how reputation progresses
- whether XP is usable
- whether it is committed
- whether the identity is still alive
This is why XP behaves like a living runtime identity.
Core Runtime Storage
These are the primary storage structures used by the pallet.
1. XpOfโ
The main storage map for XP state.
XpId => Xp
This stores the full behavioral state of every XP identity. โ๏ธ
What It Containsโ
Each XP entry stores:
| Field | Meaning |
|---|---|
free | Liquid XP (Spendable) |
reserve | Reserved XP (Usable) |
lock | Locked XP (Restricted) |
pulse.value | Reputation level |
pulse.step | Progress toward next pulse |
timestamp | Last activity block |
This is the most important storage item in the entire pallet.
Why It Mattersโ
XpOf is where:
- XP earning updates happen
- pulse progression is tracked
- inactivity is determined
- reward scaling is derived
Without XpOf, XP does not exist.
2. XpOwnersโ
Maps ownership between accounts and XP identities.
(AccountId, XpId) => ()
This defines:
who controls which XP identity
It is implemented as an ownership index for fast validation.
Why It Mattersโ
Used for:
- authorization checks
- execution validation
- ownership transfer
- listing all XP keys for an account
This powers:
ensure(owner(origin, XpId))
Without this, XP-scoped execution would not be secure ๐
3. ReservedXpOfโ
Stores all reserve constraints for each XP identity.
XpId => Vec<IdXp<ReserveReason, Value>>
Each entry contains:
- reserve reason
- reserved amount
Bounded by the number of reserve reason variants.
Why It Mattersโ
This enables:
- governance deposits
- proposal participation
- temporary allocations
- reason-scoped reservations
Reserve is soft constraint storage ๐ฆ
4. LockedXpOfโ
Stores all hard lock constraints for each XP identity.
XpId => Vec<IdXp<LockReason, Value>>
Each entry contains:
- lock reason
- locked amount
Also bounded by reason enum size.
Why It Mattersโ
This enables:
- staking
- protocol-enforced commitments
- pulse acceleration
- reaping protection
Lock is hard constraint storage ๐
5. ReapedXpโ
Blacklist of permanently removed XP identities.
XpId => ()
Once reaped:
- XP cannot be recreated
- identity cannot be reused
This prevents resurrection attacks.
Why It Mattersโ
Reaping is final.
This storage guarantees:
deleted XP stays deleted
which is critical for protocol safety ๐งน
Global Configuration Storage
These are runtime-wide system parameters.
They are stored on-chain and can be updated by root.
They are not compile-time constants.
6. MinPulseโ
Minimum reputation required before XP rewards begin.
MinPulse<Pulse>
Before this threshold:
- actions build Pulse only
After reaching it:
- XP rewards activate
This is the warmup gate ๐ฆ
7. InitXpโ
Initial XP assigned to newly created identities.
InitXp<Points>
Every new XpId begins with this value.
This creates predictable initialization behavior.
8. PulseFactorโ
Controls how Pulse grows.
PulseFactor<Stepper>
Contains:
thresholdper_count
Behaviorโ
step += per_count
if step >= threshold:
pulse += 1
step resets
This controls how fast reputation grows ๐
9. MinTimeStampโ
Minimum liveness threshold.
MinTimeStamp<BlockNumber>
If:
timestamp < MinTimeStamp
AND no active locks
then:
- XP becomes inactive
- it becomes eligible for reaping
This powers liveness enforcement.
Storage Relationships
This shows how runtime behavior depends on storage interaction.
Read vs Write Patternsโ
Not all storage is mutated equally.
Frequently Writtenโ
XpOfLockedXpOfReservedXpOf
These change during normal protocol activity.
Examples:
- earning XP
- locking
- reserving
- pulse updates
Rarely Writtenโ
MinPulseInitXpPulseFactorMinTimeStamp
These are governance-level configuration values.
Usually changed only by Root.
Write Once (Mostly)โ
ReapedXp
Once written, it should never be reversed.
This is final-state storage โ ๏ธ
Design Propertiesโ
1. Identity-Centricโ
Everything is keyed by XpId, not accounts or balances.
This preserves execution scope.
2. Reason-Isolatedโ
Locks and reserves are separated by explicit reason identifiers.
This prevents conflicts across pallets.
3. Reaping-Safeโ
Deleted identities are permanently blacklisted.
This prevents state resurrection.
4. Runtime-Configurableโ
System behavior can evolve without migrations.
Configuration lives in storage.
Final Insightโ
๐๏ธ Storage in
pallet-xpdoes not just track value. It tracks identity, behavior, commitment, and liveness.
That is why XP behaves like a protocol-native identity system, not a balance pallet.
๐ Next Stepsโ
To understand how traits dispatch and execution work internally:
๐ Architecture -> Traits