rewardstate

package
v0.65.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 16, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package rewardstate holds reward_live_stake and reward snapshot metadata query logic shared by the sqlite, mysql, and postgres metadata plugins. The SQL is identical across backends except for a handful of dialect literals (integer cast type, "transaction" table quoting, boolean literals, and whether a bound parameter needs an explicit cast). Those literals are defined once in internal/sqldialect and exposed here through the thin wrappers below, so this package cannot drift from internal/stakequery and internal/accounthistory when a backend is added or corrected.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddStakeRef

func AddStakeRef(
	refs map[string]CredentialSlotRef,
	ref models.StakeCredentialRef,
	slot uint64,
)

AddStakeRef merges one (credential, slot) pair into refs, keeping the highest slot recorded for that credential. A ref with an empty key (no staking credential on the UTxO/output) is ignored.

func CreditLiveStakeDelta

func CreditLiveStakeDelta(
	db *gorm.DB,
	ref models.StakeCredentialRef,
	amount uint64,
	slot uint64,
) (bool, error)

CreditLiveStakeDelta adds amount to an existing reward_live_stake row's reward_stake and total_stake in a single UPDATE, avoiding the full account SELECT + UTxO SUM + upsert that RefreshLiveStakeAggregate performs. This is safe only for a pure reward-stake credit: pool delegation, registered, and utxo_stake are left untouched, and the row's existing utxo_stake + (old reward_stake + amount) must still equal the new total_stake, which holds because total_stake is only ever set from a full refresh's utxoTotal+rewardStake sum.

reward_stake/total_stake are types.Uint64 columns stored as decimal-string TEXT (see types.Uint64.Value) on every backend, so the update casts to the backend's native integer type, adds, and casts back to a string type rather than relying on column affinity or implicit numeric-to-string conversion.

CreditLiveStakeDelta must run inside an active transaction. MySQL and Postgres take a SELECT ... FOR UPDATE row lock for the overflow check; SQLite drops that clause, but its single-writer transaction semantics provide the required serialization. All callers use a caller-supplied transaction or db.Transaction so the check and UPDATE remain one atomic operation.

Returns true if a row was updated; false (with no error) when no reward_live_stake row exists yet for this credential, in which case the caller must fall back to RefreshLiveStakeAggregate.

func CurrentTipSlot

func CurrentTipSlot(db *gorm.DB) (uint64, error)

CurrentTipSlot returns the metadata tip slot using the caller's transaction. A fresh database has no tip row and therefore returns slot zero.

func DeleteStateAfterSlot

func DeleteStateAfterSlot(
	db *gorm.DB,
	slot uint64,
	txn types.Txn,
) error

DeleteStateAfterSlot deletes reward-state rows captured from rolled-back blocks. When txn is non-nil, db is used as-is; otherwise the deletes are wrapped in their own transaction.

func DeleteStateBeforeEpoch

func DeleteStateBeforeEpoch(
	db *gorm.DB,
	epoch uint64,
	txn types.Txn,
) error

DeleteStateBeforeEpoch deletes reward-state rows older than the retained snapshot window. When txn is non-nil, db is used as-is; otherwise the deletes are wrapped in their own transaction.

func GetAdaPots

func GetAdaPots(
	db *gorm.DB,
	epoch uint64,
) (*models.RewardAdaPots, error)

GetAdaPots retrieves reward-related ADA pots for an epoch.

func GetPoolInputs

func GetPoolInputs(
	db *gorm.DB,
	epoch uint64,
) ([]*models.RewardPoolInput, error)

GetPoolInputs retrieves all per-pool reward inputs for an epoch.

func GetSnapshot

func GetSnapshot(
	db *gorm.DB,
	epoch uint64,
	snapshotType string,
) (*models.RewardSnapshot, error)

GetSnapshot retrieves reward snapshot metadata for an epoch.

func GroupRefsBySlot

func GroupRefsBySlot(
	refs map[string]CredentialSlotRef,
) (map[uint64][]models.StakeCredentialRef, error)

GroupRefsBySlot validates every ref in refs and groups them by the slot at which their reward-live-stake aggregate should be recomputed, skipping refs with no stake credential key. Callers use the returned map to batch-fetch certificate state (batchFetchCerts) once per slot before calling RefreshLiveStakeAggregate for each ref.

func LiveStakeNeedsBackfill

func LiveStakeNeedsBackfill(db *gorm.DB) (bool, error)

LiveStakeNeedsBackfill reports whether any canonical account or live-UTxO credential is missing from reward_live_stake. Testing for missing keys, not merely an empty aggregate, also repairs upgraded databases where post-upgrade writes populated only part of the table before the first restart.

func RebuildLiveStake

func RebuildLiveStake(db *gorm.DB, slot uint64, utxoJoinHint string) error

RebuildLiveStake fully repopulates the reward_live_stake table from current account/UTxO/certificate state. Callers are responsible for transaction scoping (db is used as-is, with no internal transaction/savepoint).

utxoJoinHint is an optional backend-specific fragment inserted immediately after `LEFT JOIN utxo` (e.g. sqlite's `INDEXED BY <index>` query-planner hint); pass "" when the backend has no equivalent syntax.

The dialect casts below are dispatched once per call via integerCastType, transactionTableName, and boolLiteral: this is the single shared SQL that replaces three near-identical per-backend copies, one of which (mysql) had drifted to omit the CAST on account.reward for the reward_stake column that postgres already applied. Casting account.reward uniformly here removes that drift by construction.

func RefreshLiveStakeAggregate

func RefreshLiveStakeAggregate(
	db *gorm.DB,
	ref models.StakeCredentialRef,
	slot uint64,
	poolDelegationCache PoolDelegationCache,
) error

RefreshLiveStakeAggregate recomputes and upserts the reward_live_stake row for a single stake credential from current account/UTxO state. This is the per-credential engine shared by RebuildLiveStake's full rebuild and every incremental refresh path (account changes, UTxO create/spend, rollback).

poolDelegationCache is the (optional) batch-fetched certificate state for this slot; nil (or a missing entry) falls back to the account row's own AddedSlot for the pool-delegation ordering, which is used for accounts imported without certificate history (e.g. genesis/Mithril bootstrap).

func SaveAdaPots

func SaveAdaPots(db *gorm.DB, pots *models.RewardAdaPots) error

SaveAdaPots saves reward-related ADA pots for an epoch.

func SavePoolInputs

func SavePoolInputs(db *gorm.DB, inputs []*models.RewardPoolInput) error

SavePoolInputs saves per-pool reward inputs for an epoch.

func SaveSnapshot

func SaveSnapshot(db *gorm.DB, snapshot *models.RewardSnapshot) error

SaveSnapshot saves reward snapshot metadata for an epoch.

func StakeRefsFromLiveUtxoIDs

func StakeRefsFromLiveUtxoIDs(
	db *gorm.DB,
	utxos []models.UtxoId,
	slot uint64,
	chunkSize int,
) (map[string]CredentialSlotRef, error)

StakeRefsFromLiveUtxoIDs is equivalent to StakeRefsFromUtxoIDs but ignores already-spent rows. Physical cleanup of spent UTxOs must not recompute live stake: the spend path already removed their value, and recomputing at a historical DeletedSlot can replace a newer delegation aggregate.

func StakeRefsFromUtxoIDs

func StakeRefsFromUtxoIDs(
	db *gorm.DB,
	utxos []models.UtxoId,
	slot uint64,
	chunkSize int,
) (map[string]CredentialSlotRef, error)

StakeRefsFromUtxoIDs resolves a batch of UTxO identifiers (tx hash + output index) to their stake credentials and merges them into a fresh credential/slot map. When slot is 0, the ref's slot is derived per-row from the UTxO's own AddedSlot/DeletedSlot (used by rollback-driven refreshes, where each UTxO may need a different recompute slot). chunkSize bounds how many UTxOs are placed in a single SQL statement.

func StakeRefsFromUtxoSpends

func StakeRefsFromUtxoSpends(
	db *gorm.DB,
	spends []UtxoSpendRef,
	chunkSize int,
) (map[string]CredentialSlotRef, error)

StakeRefsFromUtxoSpends resolves a batch of just-spent UTxOs to their stake credentials, keyed to the slot each spend was recorded at, and merges them into a fresh credential/slot map. chunkSize bounds how many spends are placed in a single SQL statement.

func ValidateLiveStakeRef

func ValidateLiveStakeRef(ref models.StakeCredentialRef) error

ValidateLiveStakeRef reports whether ref is a well-formed stake credential for the reward_live_stake table: an empty key is allowed (nothing to touch), but a non-empty key must have a valid tag (0=key, 1=script) and be exactly 28 bytes.

func ValidateLiveStakeSourceCredentials

func ValidateLiveStakeSourceCredentials(db *gorm.DB) error

ValidateLiveStakeSourceCredentials checks that every account and live-UTxO credential feeding the reward_live_stake rebuild is well-formed (tag 0 or 1, exactly 28 bytes), returning a descriptive error naming which source table and how many rows are invalid.

Types

type CredentialSlotRef

type CredentialSlotRef struct {
	Ref  models.StakeCredentialRef
	Slot uint64
}

CredentialSlotRef pairs a stake credential with the slot at which its reward-live-stake aggregate should be recomputed. Each backend keeps its own local map type (keyed the same way, via models.StakeCredentialRef.MapKey) because callers outside the scope of this package (account.go, batch_accumulator.go, transaction.go, utxo.go) destructure the map value's fields directly; this type exists for the query helpers in this file that don't need the backend-local field names.

type PoolDelegationCache

type PoolDelegationCache map[string]PoolDelegationRecord

PoolDelegationCache maps a stake credential's MapKey (see models.StakeCredentialRef.MapKey) to its most recent pool delegation certificate, as populated by each backend's batchFetchCerts. A nil cache (or a missing entry) means "no certificate history available"; callers fall back to the account row's own AddedSlot.

type PoolDelegationRecord

type PoolDelegationRecord struct {
	Pool       []byte
	AddedSlot  uint64
	BlockIndex uint64
	CertIndex  uint32
}

PoolDelegationRecord is the subset of a certificate record needed to order and apply a stake credential's most recent pool delegation. It mirrors each backend's local certRecord (defined in account.go) restricted to the fields RefreshLiveStakeAggregate needs.

type UtxoSpendRef

type UtxoSpendRef struct {
	TxId      []byte
	OutputIdx uint32
	Slot      uint64
}

UtxoSpendRef mirrors the subset of each backend's local utxoSpend row (defined in batch_accumulator.go) that StakeRefsFromUtxoSpends needs: the spent UTxO's identity and the slot the spend was recorded at.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL