Skip to main content

๐Ÿ—‚๏ธ 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:

FieldMeaning
freeLiquid XP (Spendable)
reserveReserved XP (Usable)
lockLocked XP (Restricted)
pulse.valueReputation level
pulse.stepProgress toward next pulse
timestampLast 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:

  • threshold
  • per_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โ€‹

  • XpOf
  • LockedXpOf
  • ReservedXpOf

These change during normal protocol activity.

Examples:

  • earning XP
  • locking
  • reserving
  • pulse updates

Rarely Writtenโ€‹

  • MinPulse
  • InitXp
  • PulseFactor
  • MinTimeStamp

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-xp does 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