ledger

package
v0.70.7 Latest Latest
Warning

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

Go to latest
Published: Sep 7, 2026 License: Apache-2.0 Imports: 58 Imported by: 0

Documentation

Overview

Package ledger owns Dingo's consensus-critical state: the UTxO set, protocol parameters, stake distribution, certificates, governance actions, epoch/nonce bookkeeping, and Plutus script execution. It is the authority on whether a block or transaction is valid under the active era's rules.

LedgerState is the top-level type. It is created by the node at startup, wired to the database and event bus, and consulted by the mempool, the ouroboros handlers, and the block forger.

Rollback and state restoration

When the primary chain rolls back to an earlier point, LedgerState replays state restoration against the metadata store. State restoration logic is implemented by the selected metadata backend (RestoreAccountStateAtSlot, RestorePoolStateAtSlot, RestoreDrepStateAtSlot, DeleteCertificatesAfterSlot). This package orchestrates the calls in the correct order and emits TransactionEvent with Rollback=true for each undone transaction so downstream consumers can undo their own derived state.

Epoch nonces (Ouroboros Praos)

Epoch nonce computation differs between TPraos (Shelley–Alonzo) and Praos (Babbage–Conway). The per-era formulas live in ledger/eras/, and CalculateEtaVConway / CalculateEtaVBabbage apply the Praos "N"-prefixed VRF domain separation before accumulating into the rolling nonce. The stability window for nonce freezing is 4k/f (Praos), not 3k/f (TPraos) — this matters on devnets where 4k/f can exceed the epoch length.

Sub-packages

  • ledger/forging — block production (BlockForger, BlockBuilder)
  • ledger/leader — VRF leader election for block production
  • ledger/snapshot — stake snapshot capture at epoch boundaries
  • ledger/eras — per-era validation rule implementations

Index

Constants

View Source
const (
	BlockfetchEventType                 event.EventType = "ledger.blockfetch"
	BlockEventType                      event.EventType = "ledger.block"
	ChainsyncEventType                  event.EventType = "ledger.chainsync"
	ChainsyncAwaitReplyEventType        event.EventType = "ledger.chainsync_await_reply"
	ConnectionClosedEventType           event.EventType = "ledger.conn_closed"
	ConnectionRecycleRequestedEventType event.EventType = "ledger.connection_recycle_requested"
	LedgerErrorEventType                event.EventType = "ledger.error"
	PoolStateRestoredEventType          event.EventType = "ledger.pool_restored"
	TransactionEventType                event.EventType = "ledger.tx"
)
View Source
const MaxLocalStateQueryItems = 1000

MaxLocalStateQueryItems bounds caller-controlled collections on query paths that perform database work for each requested item. Explicit over-limit filters are rejected before database access.

Variables

View Source
var (
	CloseDBWorkerPoolShutdownTimeout = 15 * time.Second
	// A Leios block-processing transaction can include a large endorser
	// closure and legitimately outlive the short blockfetch waits. Keep this
	// below Node's default 30-second shutdown budget so the later ledger and
	// database cleanup stages retain time to finish if processing is stuck.
	CloseProcessBlocksDrainTimeout = 20 * time.Second
	CloseBlockPipelineDrainTimeout = 10 * time.Second
	CloseBlockfetchDrainTimeout    = 10 * time.Second
	CloseResultReplayTimeout       = 10 * time.Second
	// BlockPipelineRollbackDrainTimeout bounds how long an asynchronous
	// rollback (chainsync fork resolution or a peer-reported rollback --
	// see rollbackChainAndStateDeferred) waits for ls.blockPipeline to drain
	// in-flight decode/validate work before proceeding. See
	// drainBlockPipelineBeforeRollback's doc comment for what this
	// protects against and, just as importantly, what it does not.
	// Exported, like the Close* timeouts above, so tests can shrink it
	// instead of running a real multi-second wait.
	BlockPipelineRollbackDrainTimeout = 5 * time.Second
)

CloseDBWorkerPoolShutdownTimeout, CloseProcessBlocksDrainTimeout, and CloseBlockfetchDrainTimeout bound the corresponding waits in Close() below. Exported (not local consts) so tests — including cross-package node-level tests exercising how a caller reacts to Close failing to confirm drain — can shrink them instead of running real multi-second timeouts.

View Source
var ErrBeforeGenesis = errors.New("time is before genesis start")

ErrBeforeGenesis is returned by TimeToSlot when the given time is before the chain's genesis start. The caller should wait until genesis.

View Source
var ErrLocalStateQueryLimitExceeded = errors.New(
	"local state query item limit exceeded",
)

ErrLocalStateQueryLimitExceeded identifies a LocalStateQuery request whose caller-controlled item count exceeds MaxLocalStateQueryItems.

View Source
var ErrNilDecodedOutput = errors.New("nil decoded output")

ErrNilDecodedOutput is returned when a decoded UTxO output is nil.

View Source
var ErrNoAppliedAncestorBelowContestedSlot = errors.New(
	"no applied ancestor below contested slot",
)

ErrNoAppliedAncestorBelowContestedSlot reports that a rollback target shares the applied tip's slot with a different hash and no applied ancestor below that slot could be found to rewind to. The contested slot's effects cannot be truncated in place, so the rollback fails loudly rather than reporting a repair that left the UTxO set diverged.

View Source
var ErrNotImplemented = errors.New("not implemented")

ErrNotImplemented marks LedgerView stubs that are not implemented yet.

View Source
var ErrRollbackExceedsMithrilBoundary = errors.New(
	"rollback exceeds Mithril trust boundary",
)
View Source
var ErrRollbackLoopDetected = errors.New(
	"rollback loop detected: same slot rolled back too many times within window",
)

ErrRollbackLoopDetected is returned by handleEventChainsyncRollback when the same peer repeatedly requests a rollback to the same slot within the rollback loop detection window. The rollback is skipped to break the loop, and the caller should trigger a chainsync re-sync to recover.

View Source
var ErrUtxoAlreadyConsumed = errors.New("UTxO already consumed")

ErrUtxoAlreadyConsumed is returned when a UTxO has been consumed by a pending transaction.

Functions

func CalculateMinFee added in v0.22.0

func CalculateMinFee(
	txSize uint64,
	exUnits lcommon.ExUnits,
	minFeeA uint,
	minFeeB uint,
	pricesMem *big.Rat,
	pricesSteps *big.Rat,
) uint64

CalculateMinFee computes the minimum fee for a transaction using the Cardano fee formula:

fee = (minFeeA * txSize) + minFeeB + scriptFee

where:

scriptFee = ceil(pricesMem * exUnits.Memory)
          + ceil(pricesSteps * exUnits.Steps)

All arithmetic uses big.Int to match the Haskell reference implementation. Overflow is impossible with Cardano protocol parameters.

func DeclaredExUnits added in v0.22.0

func DeclaredExUnits(
	tx lcommon.Transaction,
) (lcommon.ExUnits, error)

DeclaredExUnits returns the total execution units declared across all redeemers in a transaction, including Dijkstra subtransaction witness sets. Returns an error for negative values or if the summation would overflow int64.

func EraForVersion added in v0.22.0

func EraForVersion(eraList []eras.EraDesc, majorVersion uint) (uint, bool)

EraForVersion returns the era ID for a given protocol major version, resolved against the provided runtime era table. Returns false if no era covers the given version.

func GenesisBlockHash added in v0.22.0

func GenesisBlockHash(cfg *cardano.CardanoNodeConfig) ([32]byte, error)

GenesisBlockHash returns the Byron genesis hash from config, which is used as the block hash for the synthetic genesis block that holds genesis UTxO data. This mirrors how the Shelley epoch nonce uses the Shelley genesis hash.

func HeaderProtocolMajor added in v0.45.0

func HeaderProtocolMajor(header lcommon.BlockHeader) (uint, bool)

HeaderProtocolMajor extracts the protocol major version stored in a block header. Returns (0, false) for Byron-era headers, which use a different consensus mechanism (PBFT) and do not carry a Praos-style ProtVer field.

func IsCommitteeThresholdMet added in v0.22.0

func IsCommitteeThresholdMet(
	yesVotes int,
	totalActiveMembers int,
	thresholdNumerator uint64,
	thresholdDenominator uint64,
) bool

IsCommitteeThresholdMet checks whether a committee vote threshold is met. Returns true if yesVotes / totalActiveMembers >= threshold.

Edge cases per CIP-1694:

  • If yesVotes or totalActiveMembers is negative, returns false
  • If totalActiveMembers is 0, the threshold is trivially met (no committee means no committee can block)
  • If threshold numerator is 0, any vote count satisfies it
  • If threshold denominator is 0, this is treated as an error condition and returns false

func IsCompatibleEra added in v0.22.0

func IsCompatibleEra(txEraId, ledgerEraId uint) bool

IsCompatibleEra checks if a transaction era is valid for the current ledger era. Cardano allows transactions from the current era and (current era - 1).

func IsHardForkTransition added in v0.22.0

func IsHardForkTransition(
	eraList []eras.EraDesc,
	oldVersion, newVersion ProtocolVersion,
) bool

IsHardForkTransition returns true if the new protocol version triggers an era change compared to the old version.

func IsHeaderVerificationDeferred added in v0.69.0

func IsHeaderVerificationDeferred(err error) bool

IsHeaderVerificationDeferred reports whether header-only verification could not proceed because required ledger state, epoch data, or stake snapshot data is not available yet.

func TxBodySize added in v0.22.0

func TxBodySize(tx lcommon.Transaction) uint64

TxBodySize is a deprecated alias for TxSizeForFee.

func TxSizeForFee added in v0.22.0

func TxSizeForFee(tx lcommon.Transaction) uint64

TxSizeForFee computes the transaction size used in the Cardano fee formula. See eras.TxSizeForFee.

func ValidateCheckpoint added in v0.56.0

func ValidateCheckpoint(
	checkpoints map[uint64]string,
	blockNo uint64,
	hash string,
) error

ValidateCheckpoint enforces a set of configured chain checkpoints against a single block. The checkpoints map is keyed by block number (height) with the expected block hash as a hex string.

It returns nil when no checkpoints are configured, when there is no checkpoint at the given height, or when the block hash matches the configured checkpoint (case-insensitively). It returns a *CheckpointMismatchError when the height is checkpointed but the hash differs.

Honest chains always agree with the shipped checkpoints, so this rule can only reject a block on a divergent chain; it never rejects a block on the canonical chain.

func ValidateHeaderProtocolVersion added in v0.45.0

func ValidateHeaderProtocolVersion(
	header lcommon.BlockHeader,
	curPvMajor uint,
	isMainnet bool,
) error

ValidateHeaderProtocolVersion enforces cardano-ledger's BBODY-rule check that a block header's protocol major version is not more than one ahead of the current pparams protocol major version. A header equal to or one greater than current is accepted; anything beyond that is rejected with HeaderProtocolVersionTooHighError.

The check is skipped on testnets (isMainnet == false) while the current pparams major version is below Dijkstra (12). This mirrors the relaxation introduced in cardano-ledger PR 5785 to support ephemeral testnets that enable experimental hard forks or rebuild chains in much older eras.

Byron-era headers are also skipped, as they have no ProtVer field.

func ValidateTxEra added in v0.22.0

func ValidateTxEra(
	tx lcommon.Transaction,
	ledgerEraId uint,
) error

ValidateTxEra checks that a transaction's era is compatible with the current ledger era. Returns *gouroboros/ledger.EraMismatch on mismatch — a typed error whose MarshalCBOR matches the Haskell HardForkApplyTxErrWrongEra wire format, so when surfaced through localtxsubmission's SubmitTxFunc it reaches peers as canonical CBOR rather than an unstructured string.

func ValidateTxExUnits added in v0.22.0

func ValidateTxExUnits(
	totalExUnits lcommon.ExUnits,
	maxTxExUnits lcommon.ExUnits,
) error

ValidateTxExUnits checks that total execution units do not exceed the protocol parameter per-transaction limits.

func ValidateTxFee added in v0.22.0

func ValidateTxFee(
	tx lcommon.Transaction,
	minFeeA uint,
	minFeeB uint,
	pricesMem *big.Rat,
	pricesSteps *big.Rat,
) error

ValidateTxFee checks that the fee declared in the transaction body is at least the calculated minimum fee, including both the base fee component and the script execution fee component.

func ValidateTxSize added in v0.22.0

func ValidateTxSize(
	tx lcommon.Transaction,
	maxTxSize uint,
) error

ValidateTxSize checks that the transaction size does not exceed the protocol parameter maximum.

Types

type BlockAction added in v0.22.0

type BlockAction string

It represents the direction a block is applied to the ledger.

const (
	BlockActionApply BlockAction = "Apply"
	BlockActionUndo  BlockAction = "Undo"
)

type BlockEvent added in v0.22.0

type BlockEvent struct {
	Action BlockAction
	Block  models.Block
	Point  ocommon.Point
}

It represents a persisted block apply or rollback action.

type BlockfetchEvent

type BlockfetchEvent struct {
	ConnectionId ouroboros.ConnectionId // Connection ID associated with event
	Block        ledger.Block
	Point        ocommon.Point // Chain point for block
	Type         uint          // Block type ID
	BatchDone    bool          // Set to true for a BatchDone event
}

BlockfetchEvent represents either a Block or BatchDone blockfetch event. We use a single event type for both to make synchronization easier.

type BlockfetchLatencyFunc added in v0.39.0

type BlockfetchLatencyFunc func(ouroboros.ConnectionId) (time.Duration, bool)

BlockfetchLatencyFunc returns the EWMA first-block latency for the given connection and whether any samples have been recorded. Used to gate shadow blockfetch dispatch on primary peer slowness.

type BlockfetchLatencyMedianFunc added in v0.39.0

type BlockfetchLatencyMedianFunc func() (time.Duration, int)

BlockfetchLatencyMedianFunc returns the median EWMA first-block latency across all tracked peers and the sample count contributing to it. Used to adapt the shadow blockfetch gate to the observed peer population (primary > 1.5× median triggers shadow dispatch).

type BlockfetchRequestRangeFunc

type BlockfetchRequestRangeFunc func(ouroboros.ConnectionId, ocommon.Point, ocommon.Point) error

BlockfetchRequestRangeFunc describes a callback function used to start a blockfetch request for a range of blocks

type ChainsyncAwaitReplyEvent added in v0.27.7

type ChainsyncAwaitReplyEvent struct {
	ConnectionId ouroboros.ConnectionId
}

ChainsyncAwaitReplyEvent is emitted when a chainsync peer explicitly reports it has no additional headers to send right now.

type ChainsyncEvent

type ChainsyncEvent struct {
	ConnectionId ouroboros.ConnectionId // Connection ID associated with event
	BlockHeader  ledger.BlockHeader
	// ArrivalTime is recorded immediately when the ChainSync callback receives
	// a roll-forward header. It lets ledger admission judge the peer's clock at
	// arrival even if event delivery or header processing is delayed.
	ArrivalTime time.Time
	Point       ocommon.Point  // Chain point for roll forward/backward
	Tip         ochainsync.Tip // Upstream chain tip
	// SyncTarget is the event-paired, policy-approved target eligible for
	// publication only after this header is admitted.
	SyncTarget        ochainsync.Tip
	SyncTargetTrusted bool
	BlockNumber       uint64
	Type              uint // Block or header type ID
	Rollback          bool // Set to true for a Rollback event
}

ChainsyncEvent represents either a RollForward or RollBackward chainsync event. We use a single event type for both to make synchronization easier.

type ChainsyncState added in v0.12.0

type ChainsyncState string
const (
	InitChainsyncState     ChainsyncState = "init"
	RollbackChainsyncState ChainsyncState = "rollback"
	SyncingChainsyncState  ChainsyncState = "syncing"
)

type CheckpointMismatchError added in v0.56.0

type CheckpointMismatchError struct {
	BlockNo  uint64
	Expected string
	Actual   string
}

CheckpointMismatchError is returned when a block at a configured checkpoint height has a hash that differs from the expected one. This is an envelope-validity failure: the block sits on a chain that diverges from the known-good chain at a checkpointed height, so it must be rejected regardless of any other validity it might have.

func (*CheckpointMismatchError) Error added in v0.56.0

func (e *CheckpointMismatchError) Error() string

type ClearSeenHeadersFromFunc added in v0.27.7

type ClearSeenHeadersFromFunc func(fromSlot uint64)

ClearSeenHeadersFromFunc clears the header dedup cache for slots beyond the given slot. This allows headers that were discarded (e.g. by clearQueuedHeaders) to be re-delivered on reconnection.

type ConnectionClosedEvent added in v0.55.0

type ConnectionClosedEvent struct {
	ConnectionId ouroboros.ConnectionId
	Error        error
}

ConnectionClosedEvent is emitted by the node layer when a connection closes. Ledger subscribes to this ledger-owned event type instead of connmanager directly, so ledger/ does not need to import connmanager/.

type ConnectionLiveFunc added in v0.32.2

type ConnectionLiveFunc func(ouroboros.ConnectionId) bool

ConnectionLiveFunc reports whether a connection is still registered with the connection manager. This allows the ledger to drop late chainsync events that arrive after teardown.

type ConnectionRecycleRequestedEvent added in v0.55.0

type ConnectionRecycleRequestedEvent struct {
	ConnectionId ouroboros.ConnectionId
	Reason       string
}

ConnectionRecycleRequestedEvent is emitted by the ledger when header or block crypto verification fails on a peer connection. Node wiring translates this to a connmanager recycle request, keeping ledger/ free of connmanager/ imports.

type ConnectionSwitchFunc added in v0.22.0

type ConnectionSwitchFunc func()

ConnectionSwitchFunc is called when the active chainsync connection changes. Implementations should clear any per-connection state such as the header dedup cache so the new connection can re-deliver blocks.

type DatabaseOperation added in v0.19.0

type DatabaseOperation struct {
	// Operation function that performs the database work
	OpFunc func(db *database.Database) error
	// Channel to send the result back. Must be non-nil and buffered to avoid blocking.
	// If nil, the operation will be executed but the result will be discarded (fire and forget).
	ResultChan chan<- DatabaseResult
}

DatabaseOperation represents an asynchronous database operation

type DatabaseResult added in v0.19.0

type DatabaseResult struct {
	Error error
}

DatabaseResult represents the result of a database operation

type DatabaseWorkerPool added in v0.19.0

type DatabaseWorkerPool struct {
	// contains filtered or unexported fields
}

DatabaseWorkerPool manages a pool of workers for async database operations

func NewDatabaseWorkerPool added in v0.19.0

func NewDatabaseWorkerPool(
	db *database.Database,
	config DatabaseWorkerPoolConfig,
) *DatabaseWorkerPool

NewDatabaseWorkerPool creates a new database worker pool

func (*DatabaseWorkerPool) Shutdown added in v0.19.0

func (p *DatabaseWorkerPool) Shutdown(drainTimeout time.Duration) error

Shutdown stops accepting new operations, then waits for every already accepted one to finish and the worker goroutines to exit.

The drain wait is bounded by drainTimeout -- callers pass CloseDBWorkerPoolShutdownTimeout, the same budget LedgerState.Close's own outer wait around the goroutine that calls Shutdown already uses. Close's outer wait keeps Close itself from blocking past that budget regardless of what Shutdown does, but a bound is still needed here: without one, a caller of Shutdown that gives up (like that outer wait) leaves nothing waiting on the drain at all, so a still-running worker's operation (and the resources it holds, e.g. this pool's db) would never be observed finishing -- and the fix could recur for any future operation slower than expected, not just the O(n^2) query bug this once surfaced as (see the account-lookup fix this guards against regressing).

The wait itself selects the drained channel directly rather than spawning a goroutine to block on a sync.WaitGroup: WaitGroup.Wait cannot be selected against a timeout, so a wrapper goroutine bridging it to a channel would still block for the slow operation's full remaining duration after Shutdown times out and returns -- trading the caller's leak for an internal one instead of removing it. drained is closed by whichever of Shutdown or operationDone observes the closed-and-drained transition first, so no goroutine is ever spawned here.

drainTimeout is a parameter rather than a direct read of CloseDBWorkerPoolShutdownTimeout so a test that mutates that var for isolation (see state_test.go) cannot race this call: Close evaluates the argument once, synchronously, before calling Shutdown.

func (*DatabaseWorkerPool) Submit added in v0.19.0

func (p *DatabaseWorkerPool) Submit(op DatabaseOperation)

Submit submits a database operation for async execution

type DatabaseWorkerPoolConfig added in v0.19.0

type DatabaseWorkerPoolConfig struct {
	WorkerPoolSize int
	TaskQueueSize  int
	Disabled       bool
}

DatabaseWorkerPoolConfig holds configuration for the database worker pool

func DefaultDatabaseWorkerPoolConfig added in v0.19.0

func DefaultDatabaseWorkerPoolConfig() DatabaseWorkerPoolConfig

DefaultDatabaseWorkerPoolConfig returns the default configuration for the database worker pool

type EndorserBlockFetcherFunc added in v0.58.0

type EndorserBlockFetcherFunc func(
	ctx context.Context,
	ebSlot uint64,
	ebHash []byte,
) error

EndorserBlockFetcherFunc actively fetches the endorser block identified by (ebSlot, ebHash) over leios-fetch (manifest plus all transaction bodies) and caches it so a subsequent EndorserBlockProviderFunc call returns it. It returns an error when no fetch connection is available or the relay does not serve the block. The endorser block shares the slot of the ranking block that references it (they are co-produced), so ebSlot is the ranking block's slot.

ctx bounds the whole fetch, including its per-connection failover. The caller owns the budget: block application waits for this fetch, so an implementation must not outlive the context it was handed (dingo #3552).

type EndorserBlockProviderFunc added in v0.56.0

type EndorserBlockProviderFunc func(
	ebHash []byte,
	ebSlot uint64,
) (txs []cbor.RawMessage, ok bool)

EndorserBlockProviderFunc returns the complete set of standalone transaction CBORs of the Leios endorser block identified by (ebHash, ebSlot), when exactly that occurrence has been fetched and fully cached; ok is false otherwise. ebSlot is required, not merely advisory: the manifest is content-addressed, so the same hash can be a live, independently required occurrence at more than one slot at once, and the provider must resolve exactly the occurrence the caller's own reference names rather than whichever one happens to be cached for the hash (issue #3513 review). It is used to apply an endorser block's transactions to the ledger when the referencing Dijkstra ranking block is processed.

type EpochInfo added in v0.22.0

type EpochInfo struct {
	EpochId       uint64
	StartSlot     uint64
	LengthInSlots uint
}

EpochInfo contains epoch boundary information

func (EpochInfo) EndSlot added in v0.22.0

func (e EpochInfo) EndSlot() uint64

EndSlot returns the first slot of the next epoch (one past the last slot of this epoch)

type EpochRolloverResult added in v0.21.0

type EpochRolloverResult struct {
	NewEpochCache             []models.Epoch
	NewCurrentEpoch           models.Epoch
	NewCurrentEra             eras.EraDesc
	NewCurrentPParams         lcommon.ProtocolParameters
	NewEpochNum               float64
	CheckpointWrittenForEpoch bool
	SchedulerIntervalMs       uint
	// HardFork is non-nil when a protocol version change
	// in the updated pparams triggers an era transition.
	HardFork *HardForkInfo
	// BoundarySnapshotDeferred is true when the caller asked
	// processEpochRollover to skip the authoritative mark-snapshot capture and
	// the rollover reached the point where it would otherwise have captured it.
	// The caller then owns exactly one capture, taken after the remaining
	// boundary era transitions have rewritten NewCurrentEra and
	// NewCurrentPParams. It stays false for the initial-epoch path, which never
	// captures a mark snapshot.
	BoundarySnapshotDeferred bool
	// RealV2CostModelObserved is true when this rollover's enacted governance
	// ParamUpdate explicitly carried a PlutusV2 cost model
	// (governance.EnactmentResult.PlutusV2CostModelWritten), not merely
	// whether the post-enactment pparams happen to contain one. Provenance
	// is tracked from the enacted delta itself rather than by comparing
	// before/after values, because DefaultPlutusV2CostModel is the real
	// canonical mainnet value: real governance re-affirming it verbatim
	// would be indistinguishable from "unchanged" under a value-comparison
	// approach, which would then never clear
	// LedgerState.syntheticV2CostModel on a real network. See
	// blinklabs-io/dingo#3825's PR review.
	RealV2CostModelObserved bool
}

EpochRolloverResult holds computed state from epoch rollover

type EraTransitionResult added in v0.21.0

type EraTransitionResult struct {
	NewPParams lcommon.ProtocolParameters
	NewEra     eras.EraDesc
	// InjectedSyntheticV2CostModel is true when this specific transition is
	// the one that fabricated a PlutusV2 cost model (HardForkBabbage's
	// default), as opposed to one carried forward from a real source. See
	// LedgerState.syntheticV2CostModel.
	InjectedSyntheticV2CostModel bool
}

EraTransitionResult holds computed state from an era transition

type FatalErrorFunc added in v0.21.0

type FatalErrorFunc func(err error)

FatalErrorFunc is a callback invoked when a fatal error occurs that requires the node to shut down. The callback should trigger graceful shutdown.

type ForgedBlockChecker added in v0.22.0

type ForgedBlockChecker interface {
	// WasForgedByUs returns the block hash and true if the local node
	// forged a block for the given slot, or nil and false otherwise.
	WasForgedByUs(slot uint64) (blockHash []byte, ok bool)
}

ForgedBlockChecker is an interface for checking whether the local node recently forged a block for a given slot. This is used by chainsync to detect slot battles when an incoming block from a peer occupies the same slot as a locally forged block.

type GenesisSelectionStateFunc added in v0.69.0

type GenesisSelectionStateFunc func() (active bool, window uint64)

GenesisSelectionStateFunc returns whether authoritative fork resolution should use Ouroboros Genesis density and the active window in slots.

type GetActiveConnectionFunc added in v0.21.0

type GetActiveConnectionFunc func() *ouroboros.ConnectionId

GetActiveConnectionFunc is a callback to retrieve the currently active chainsync connection ID for chain selection purposes.

type GetPeerObservedTipFunc added in v0.70.1

type GetPeerObservedTipFunc func(
	ouroboros.ConnectionId,
) (ochainsync.Tip, bool)

GetPeerObservedTipFunc returns the delivered frontier tracked for a peer. The boolean is false when the connection is no longer tracked.

type GetPeerSyncTargetFunc added in v0.70.3

type GetPeerSyncTargetFunc func(
	ouroboros.ConnectionId,
) (ochainsync.Tip, bool)

GetPeerSyncTargetFunc returns a corroborated remote sync target.

type HardForkInfo added in v0.22.0

type HardForkInfo struct {
	OldVersion ProtocolVersion
	NewVersion ProtocolVersion
	FromEra    uint
	ToEra      uint
}

HardForkInfo holds details about a detected hard fork transition, populated when a protocol parameter update at an epoch boundary changes the protocol major version into a new era.

type HeaderProtocolVersionTooHighError added in v0.45.0

type HeaderProtocolVersionTooHighError struct {
	Supplied uint
	Expected uint
}

HeaderProtocolVersionTooHighError is returned when a block header's protocol major version is more than one ahead of the current pparams protocol major version. Mirrors cardano-ledger's HeaderProtVerTooHigh failure from the BBODY rule.

func (*HeaderProtocolVersionTooHighError) Error added in v0.45.0

type LedgerDelta added in v0.7.0

type LedgerDelta struct {
	Point        ocommon.Point
	BlockEraId   uint
	BlockNumber  uint64
	Transactions []TransactionRecord
	Offsets      *database.BlockIngestionResult // pre-computed CBOR offsets for this block
	// contains filtered or unexported fields
}

func NewLedgerDelta added in v0.18.0

func NewLedgerDelta(
	point ocommon.Point,
	blockEraId uint,
	blockNumber uint64,
) *LedgerDelta

func (*LedgerDelta) Release added in v0.18.0

func (d *LedgerDelta) Release()

type LedgerDeltaBatch added in v0.8.0

type LedgerDeltaBatch struct {
	// contains filtered or unexported fields
}

func NewLedgerDeltaBatch added in v0.18.0

func NewLedgerDeltaBatch() *LedgerDeltaBatch

func (*LedgerDeltaBatch) Release added in v0.18.0

func (b *LedgerDeltaBatch) Release()

type LedgerErrorEvent added in v0.21.0

type LedgerErrorEvent struct {
	Error     error         // The actual error that occurred
	Operation string        // The operation that failed (e.g., "block_header", "rollback")
	Point     ocommon.Point // Chain point where the error occurred, if applicable
}

LedgerErrorEvent represents an error that occurred during ledger processing.

type LedgerState

type LedgerState struct {
	Scheduler *Scheduler

	sync.RWMutex
	// contains filtered or unexported fields
}

func NewLedgerState

func NewLedgerState(cfg LedgerStateConfig) (*LedgerState, error)

func (*LedgerState) ActiveSlotCoeff added in v0.22.0

func (ls *LedgerState) ActiveSlotCoeff() float64

ActiveSlotCoeff returns the active slot coefficient (f parameter). This is used in the Ouroboros Praos leader election probability.

func (*LedgerState) ActiveSlotCoeffRat added in v0.69.0

func (ls *LedgerState) ActiveSlotCoeffRat() *big.Rat

ActiveSlotCoeffRat returns the active slot coefficient (f) as an exact *big.Rat taken straight from the Shelley genesis, with no float64 roundtrip. Returns nil when the genesis is unavailable.

Prefer this over ActiveSlotCoeff for anything that feeds a leader check. ActiveSlotCoeff divides the genesis numerator and denominator as float64, and the nearest double to a value like 1/20 is strictly larger than 1/20, so a threshold derived from it is strictly larger than the reference node's and admits a strict superset of eligible slots. Both the header-verification path and the leader-schedule precompute must use this exact value so they cannot disagree with each other or with the reference.

func (*LedgerState) AwaitChainsyncHeaderAdmission added in v0.70.1

func (ls *LedgerState) AwaitChainsyncHeaderAdmission(
	ctx context.Context,
	e ChainsyncEvent,
) (bool, error)

AwaitChainsyncHeaderAdmission enforces the Ouroboros ChainSync future-header rule against the timestamp recorded at network ingress. It must run from the per-peer ChainSync callback before the header updates observed-tip, dedup, or ledger state; callers must not invoke it while holding the node-wide chainsync dispatch mutex.

A header received no more than defaultHeaderClockSkew before its slot waits for slot onset and is accepted. A header received earlier is deliberately dropped by returning (false, nil): local clock skew cannot by itself justify penalizing the peer. ErrPastHorizon is also accepted as a deferred decision, matching headerVerificationEpoch; without a forecast the header cannot be proven future. Other conversion failures fail closed. A zero timestamp is retained for compatibility with synthetic/internal events that never crossed the network ingress path. As with other Go APIs that accept a context, ctx must not be nil.

func (*LedgerState) BlockByHash added in v0.21.0

func (ls *LedgerState) BlockByHash(hash []byte) (models.Block, error)

BlockByHash returns a block by its hash.

func (*LedgerState) ByronProtocolMagic added in v0.70.0

func (ls *LedgerState) ByronProtocolMagic() (uint32, error)

ByronProtocolMagic returns the protocol magic configured in Byron genesis.

func (*LedgerState) CardanoNodeConfig added in v0.21.0

func (ls *LedgerState) CardanoNodeConfig() *cardano.CardanoNodeConfig

CardanoNodeConfig returns the Cardano node configuration used for this ledger state.

func (*LedgerState) Chain

func (ls *LedgerState) Chain() *chain.Chain

func (*LedgerState) ChainTipSlot added in v0.22.0

func (ls *LedgerState) ChainTipSlot() uint64

ChainTipSlot returns the slot number of the current chain tip.

func (*LedgerState) Close

func (ls *LedgerState) Close() (retErr error)

func (*LedgerState) ConsensusModeForEpoch added in v0.39.3

func (ls *LedgerState) ConsensusModeForEpoch(
	epoch uint64,
) consensus.ConsensusMode

ConsensusModeForEpoch returns the Praos consensus variant that governs leader eligibility for the given epoch. Shelley/Allegra/ Mary/Alonzo run TPraos; Babbage/Conway run CPraos. Anything else (including Byron and unknown eras) defaults to CPraos, matching how block production paths fall back today.

Resolution order, mirroring how the leader-election caller can be computing the schedule for the current epoch or pre-computing the next one across a scheduled hard fork:

  1. Look up the epoch's stored EraId in epochCache (set by the epoch rollover when the epoch is created).
  2. If we don't have that epoch yet (precompute path) and a hard fork has been confirmed via HardForkInitiation, transitionInfo pins the first epoch of the next era; advance once when the target epoch is at or past that boundary.
  3. Otherwise forecast the era forward from the current era using the schedule's TriggerAtEpoch trigger (TestXHardForkAtEpoch overrides surface here too), advancing once per scheduled boundary at-or-before the target epoch.
  4. Fall back to the current era if nothing applies.

func (*LedgerState) CountBlocksInSlotRange added in v0.29.0

func (ls *LedgerState) CountBlocksInSlotRange(
	startSlot, endSlot uint64,
) (int, uint64, uint64, error)

CountBlocksInSlotRange returns the number of canonical blocks in the inclusive slot range [startSlot, endSlot], along with the first and last block slots found. It uses canonical metadata rows instead of raw blob keys so orphaned fork blocks do not leak into Blockfrost epoch responses.

func (*LedgerState) CountTransactionsByAddress added in v0.33.0

func (ls *LedgerState) CountTransactionsByAddress(
	addr lcommon.Address,
) (int, error)

CountTransactionsByAddress returns the total number of transactions involving the given address.

func (*LedgerState) CountTransactionsByMetadataLabel added in v0.34.0

func (ls *LedgerState) CountTransactionsByMetadataLabel(
	label uint64,
) (int, error)

CountTransactionsByMetadataLabel returns the total number of transactions that include metadata for the requested label.

func (*LedgerState) CountTransactionsInSlotRange added in v0.29.0

func (ls *LedgerState) CountTransactionsInSlotRange(
	startSlot, endSlot uint64,
) (int, error)

CountTransactionsInSlotRange returns the number of transactions whose slot falls within the inclusive range [startSlot, endSlot]. Used by the Blockfrost adapter CurrentEpoch() path so epoch responses can return real tx counts without decoding every block in the epoch on demand.

func (*LedgerState) CurrentEpoch added in v0.22.0

func (ls *LedgerState) CurrentEpoch() uint64

CurrentEpoch returns the current epoch number.

func (*LedgerState) CurrentOrTipSlot added in v0.32.0

func (ls *LedgerState) CurrentOrTipSlot() uint64

CurrentOrTipSlot returns the current wall-clock slot if available, or the current chain tip slot when the slot clock is unavailable. When both are available, it returns whichever slot is ahead.

func (*LedgerState) CurrentSlot added in v0.22.0

func (ls *LedgerState) CurrentSlot() (uint64, error)

CurrentSlot returns the current slot number based on wall-clock time. Delegates to the internal slot clock.

func (*LedgerState) CurrentTransitionInfo added in v0.36.0

func (ls *LedgerState) CurrentTransitionInfo() hardfork.TransitionInfo

CurrentTransitionInfo returns the current TransitionInfo from the lock-free consensus snapshot.

func (*LedgerState) Database added in v0.22.0

func (ls *LedgerState) Database() *database.Database

Database returns the underlying database for transaction operations.

func (*LedgerState) Datum added in v0.18.0

func (ls *LedgerState) Datum(hash []byte) (*models.Datum, error)

Datum looks up a datum by hash & adding this for implementing query.ReadData #741

func (*LedgerState) DelegatorInactivityConfig added in v0.69.0

func (ls *LedgerState) DelegatorInactivityConfig() (enabled bool, window uint64)

DelegatorInactivityConfig reports the CIP-0163 delegator-inactivity gate as this LedgerState was actually constructed with. Exported so callers outside the ledger package (e.g. a regression test proving these values survive a live restore/truncate's LedgerState reinitialization, the same kind of construction-site drift MinPoolMargin/PledgeLeverageEnabled/ PledgeLeverage/FullPotRewardsEnabled were previously found missing from) can verify it without reaching into the unexported config field.

func (*LedgerState) EndorserBlockWaitDuration added in v0.66.2

func (ls *LedgerState) EndorserBlockWaitDuration() time.Duration

EndorserBlockWaitDuration returns the wall-clock window to wait for a referenced/certified endorser block's transaction closure to become available, derived from the Leios pipeline timing (EndorserBlockWaitSlots, the certify-by deadline) and the Shelley slot length. It returns 0 when the wait is disabled or the slot length is unknown. This is the same window ledger application uses to gate a ranking block on its endorser block (see ensureReferencedEndorserBlocks), so NtC serving and ledger application wait for the same healthy closure-delivery window.

func (*LedgerState) EpochInfo added in v0.63.0

func (ls *LedgerState) EpochInfo(epoch uint64) (models.Epoch, error)

EpochInfo returns boundary information for the given epoch. See SlotTimeConverter.EpochInfo for details.

func (*LedgerState) EpochNonce added in v0.22.0

func (ls *LedgerState) EpochNonce(epoch uint64) []byte

EpochNonce returns the nonce for the given epoch. The epoch nonce is used for VRF-based leader election. Returns nil if the epoch nonce is not available (e.g., for Byron era).

When the slot clock fires an epoch transition before block processing crosses the boundary, the nonce for the next epoch (currentEpoch+1) is computed speculatively from the current epoch's data. This eliminates the forging gap at epoch boundaries where the leader schedule would otherwise be unavailable until a peer's block triggers epoch rollover.

func (*LedgerState) EvaluateTx added in v0.16.0

EvaluateTx evaluates the scripts in the provided transaction and returns the calculated fee, per-redeemer ExUnits, and total ExUnits

func (*LedgerState) GetBlock

func (ls *LedgerState) GetBlock(point ocommon.Point) (models.Block, error)

func (*LedgerState) GetChainFromPoint

func (ls *LedgerState) GetChainFromPoint(
	point ocommon.Point,
	inclusive bool,
) (*chain.ChainIterator, error)

GetChainFromPoint returns a ChainIterator starting at the specified point. If inclusive is true, the iterator will start at the requested point, otherwise it will start at the next block.

func (*LedgerState) GetChainFromPointContext added in v0.49.1

func (ls *LedgerState) GetChainFromPointContext(
	ctx context.Context,
	point ocommon.Point,
	inclusive bool,
) (*chain.ChainIterator, error)

GetChainFromPointContext returns a ChainIterator that inherits cancellation from ctx.

func (*LedgerState) GetChainFromPointReverse added in v0.47.0

func (ls *LedgerState) GetChainFromPointReverse(
	point ocommon.Point,
	inclusive bool,
) (*chain.ChainIterator, error)

GetChainFromPointReverse returns a ChainIterator that walks backward from the specified point toward chain origin. If inclusive is true the iterator yields the start point first; otherwise it yields the preceding block.

func (*LedgerState) GetChainFromPointReverseContext added in v0.49.1

func (ls *LedgerState) GetChainFromPointReverseContext(
	ctx context.Context,
	point ocommon.Point,
	inclusive bool,
) (*chain.ChainIterator, error)

GetChainFromPointReverseContext returns a reverse ChainIterator that inherits cancellation from ctx.

func (*LedgerState) GetCurrentPParams

func (ls *LedgerState) GetCurrentPParams() lcommon.ProtocolParameters

GetCurrentPParams returns the currentPParams value

func (*LedgerState) GetCurrentPParamsForReporting added in v0.70.7

func (ls *LedgerState) GetCurrentPParamsForReporting() lcommon.ProtocolParameters

GetCurrentPParamsForReporting returns the current protocol parameters with HardForkBabbage's fabricated PlutusV2 cost model omitted for as long as it hasn't been replaced by real governance/protocol-update data -- matching what a real cardano-node reports (blinklabs-io/dingo#3825). This is for external reporting surfaces only: LocalStateQuery's GetCurrentProtocolParams (ledger/queries.go), and the Blockfrost/UTXORPC/Mesh API adapters that separately surface protocol parameters. Every other caller (script validation, block-building limits, Leios committee parameters, governance proposal decoding) must keep calling GetCurrentPParams: internal logic needs the real fabricated default unconditionally, since a genuine PlutusV2 script can arrive before the real update lands.

func (*LedgerState) GetEpochs added in v0.21.0

func (ls *LedgerState) GetEpochs() ([]models.Epoch, error)

It returns all epochs stored in the database.

func (*LedgerState) GetIntersectPoint

func (ls *LedgerState) GetIntersectPoint(
	points []ocommon.Point,
) (*ocommon.Point, error)

GetIntersectPoint returns the intersect between the specified points and the current chain

func (*LedgerState) GetPParamsForEpoch added in v0.21.0

func (ls *LedgerState) GetPParamsForEpoch(
	epoch uint64,
	era eras.EraDesc,
) (lcommon.ProtocolParameters, error)

It returns protocol parameters for the specific epoch.

func (*LedgerState) GetTransactionsByAddress added in v0.22.0

func (ls *LedgerState) GetTransactionsByAddress(
	addr lcommon.Address,
	limit int,
	offset int,
) ([]models.Transaction, error)

GetTransactionsByAddress returns transactions involving the given address.

func (*LedgerState) GetTransactionsByAddressWithOrder added in v0.33.0

func (ls *LedgerState) GetTransactionsByAddressWithOrder(
	addr lcommon.Address,
	limit int,
	offset int,
	order string,
) ([]models.Transaction, error)

GetTransactionsByAddressWithOrder returns transactions involving the given address with explicit ordering.

func (*LedgerState) GetTransactionsByBlockHash added in v0.22.0

func (ls *LedgerState) GetTransactionsByBlockHash(
	blockHash []byte,
) ([]models.Transaction, error)

GetTransactionsByBlockHash returns all transactions for a given block hash.

func (*LedgerState) GetTransactionsByHashes added in v0.33.0

func (ls *LedgerState) GetTransactionsByHashes(
	hashes [][]byte,
) ([]models.Transaction, error)

GetTransactionsByHashes returns transactions for the provided hashes.

func (*LedgerState) HardForkSummary added in v0.37.0

func (ls *LedgerState) HardForkSummary() (*hardfork.Summary, error)

HardForkSummary constructs a hardfork.Summary describing the chain's era history from the LedgerState's current epoch cache, tip, current era, and transition info.

The returned Summary's past eras are closed with bounds computed by walking the epoch cache grouped by EraId. The current era is passed through hardfork.BuildSummary with the safe zone from the configured era Shape and the ledger's current TransitionInfo. This gives in-memory callers the same bounded forecast inputs used by the NtC HardForkEraHistory query.

The forecast horizon is measured from the published tip. Callers that know a more recent applied block must use hardForkSummaryAnchoredAt instead.

func (*LedgerState) IntersectPoints added in v0.27.1

func (ls *LedgerState) IntersectPoints(
	count int,
) ([]ocommon.Point, error)

IntersectPoints returns chainsync FindIntersect candidates ordered from newest to oldest. The point list stays dense near the tip and spreads out deeper in history so lagging peers intersect recent chain state instead of falling back to origin after only a small tip gap.

func (*LedgerState) IsAtTip added in v0.25.1

func (ls *LedgerState) IsAtTip() bool

IsAtTip reports whether the node has caught up to the chain tip at least once since boot. This is used to gate metrics that are only meaningful when processing live blocks (e.g., block delay CDF). Unlike validationEnabled (which starts true when ValidateHistorical is set), reachedTip only flips when the node actually reaches the stability window.

func (*LedgerState) LatestOpCertSequence added in v0.43.0

func (ls *LedgerState) LatestOpCertSequence(
	poolID [28]byte,
) (sequence uint64, found bool, err error)

LatestOpCertSequence returns the highest opcert issue-number counter observed for poolID, honoring the same Mithril trust boundary block application enforces (see latestOpCertCounterAfterMithril): a plain MAX over the whole table would trust rows a Mithril import left below the certified boundary, giving startup and forge-loop credential checks a baseline block application itself does not use.

func (*LedgerState) MinPoolMargin added in v0.67.0

func (ls *LedgerState) MinPoolMargin() *big.Rat

MinPoolMargin returns the CIP-23 minimum pool margin as a rational in [0, 1], or nil when disabled (config value 0). It satisfies the eras package MinPoolMarginProvider interface used by the Dijkstra pool-margin-floor certificate rule; the Dijkstra-only era gate is inherent because only ValidateTxDijkstra consults it.

func (*LedgerState) NewView added in v0.22.0

func (ls *LedgerState) NewView(txn *database.Txn) *LedgerView

NewView creates a new LedgerView for querying ledger state within a transaction.

func (*LedgerState) NextEpochNonceReadyEpoch added in v0.27.3

func (ls *LedgerState) NextEpochNonceReadyEpoch() (uint64, bool)

NextEpochNonceReadyEpoch reports the upcoming epoch when the current epoch has already crossed the nonce stability cutoff and the next leader schedule can be precomputed immediately.

func (*LedgerState) NextSlotTime added in v0.22.0

func (ls *LedgerState) NextSlotTime() (time.Time, error)

NextSlotTime returns the wall-clock time when the next slot begins.

func (*LedgerState) OldestRequiredSnapshotEpoch added in v0.70.6

func (ls *LedgerState) OldestRequiredSnapshotEpoch() (uint64, bool)

OldestRequiredSnapshotEpoch returns the oldest pool-stake snapshot epoch that a currently queued/deferred header still needs for leader-eligibility validation, so snapshot pruning can retain it instead of removing it out from under the deferred header (issue #3727). It locks the deferred-header set and delegates to oldestRequiredSnapshotEpochLocked. Prefer PrunePoolSnapshotsWithRetentionFloor for the prune path, which holds the lock across both the floor read and the prune so admission cannot interleave; this public method exists for observation and tests.

func (*LedgerState) PoolRegistrationVRFKeyHash added in v0.43.0

func (ls *LedgerState) PoolRegistrationVRFKeyHash(
	poolID [28]byte,
) (vrfHash [32]byte, found bool, err error)

PoolRegistrationVRFKeyHash returns the VRF key hash recorded on the most recent active pool registration certificate for the given pool. found is false when the pool has no on-chain registration yet — that is informational, not an error condition, since operators commonly stage credentials before the registration certificate is on chain.

Used by the block-producer credential check at startup to confirm the loaded VRF key matches what the chain has on file.

func (*LedgerState) PoolStakeDistribution added in v0.70.0

func (ls *LedgerState) PoolStakeDistribution(
	poolFilter []lcommon.PoolKeyHash,
) (*PoolStakeDistribution, error)

PoolStakeDistribution reads the active stake distribution across block-producing pools.

The distribution comes from the mark snapshot at praos.StakeSnapshotEpoch, the same one leader election reads, rather than from live stake. A caller checking a leadership schedule against the node would otherwise be told they lead slots the node will not let them mint.

poolFilter restricts which pools are reported. A nil filter reports every pool in the snapshot. A non-nil filter reports only the pools it names, which for an empty non-nil filter is no pools at all -- the distinction matters because GetPoolDistr2's wire form can carry an explicit empty set, which means "no pools" rather than "every pool" (see olocalstatequery.ShelleyPoolDistr2Query.PoolFilter). Filtering never renormalises: TotalActiveStake stays the whole snapshot's total and each fraction stays a share of it.

A pool holding snapshot stake with no registration on record is omitted rather than reported with a zero VRF key hash, which would read as a real key. Its stake stays in TotalActiveStake, so every reported pool's own fraction is unaffected by the omission.

func (*LedgerState) PrepareEpochCacheForStartup added in v0.61.0

func (ls *LedgerState) PrepareEpochCacheForStartup() error

PrepareEpochCacheForStartup loads epoch metadata before LedgerState.Start(). It is startup-only: callers use this when another component needs SlotToEpoch before the ledger processing loop is running.

func (*LedgerState) PrimaryChainTip added in v0.31.1

func (ls *LedgerState) PrimaryChainTip() ochainsync.Tip

PrimaryChainTip returns the tip of the primary chain. This can be ahead of Tip() while the ledger pipeline is still replaying blocks into committed metadata state.

func (*LedgerState) PrimaryChainTipSlot added in v0.31.1

func (ls *LedgerState) PrimaryChainTipSlot() uint64

PrimaryChainTipSlot returns the slot number of the primary chain tip. This can be ahead of ChainTipSlot() while the ledger pipeline is still replaying blocks into committed metadata state.

func (*LedgerState) ProcessTrustedBlockBatches added in v0.25.0

func (ls *LedgerState) ProcessTrustedBlockBatches(
	ctx context.Context,
	batches <-chan []ledger.Block,
) error

ProcessTrustedBlockBatches processes already-decoded trusted block batches synchronously. This is used by immutable load so blocks can be replayed directly without first being reread from the chain store.

func (*LedgerState) ProtocolParamsForSlot added in v0.39.2

func (ls *LedgerState) ProtocolParamsForSlot(
	slot uint64,
) lcommon.ProtocolParameters

ProtocolParamsForSlot returns the protocol parameters that should govern a block forged at the given slot. When the slot lies in an epoch beyond a scheduled fork (the active era's NextEraTrigger is TriggerAtEpoch and the slot's epoch is at or past the trigger), the returned pparams are the post-fork pparams computed by walking each successor era's HardForkFunc up to the slot's era.

The forger uses this when picking an era to build a block in. Reading currentPParams alone would lock a sole producer to the pre-fork era forever: the boundary-crossing block would be encoded in the old era, the rollover (which trusts the observed block's era) would not advance, and the chain would never traverse the fork. Forecasting from the schedule lets the forger produce a block in the era the schedule requires, regardless of how the schedule was produced — administrative overrides, on-chain update proposals, or HardForkInitiation gov actions all surface as TriggerAtEpoch entries on the shape.

func (*LedgerState) PrunePoolSnapshotsWithRetentionFloor added in v0.70.6

func (ls *LedgerState) PrunePoolSnapshotsWithRetentionFloor(
	defaultBefore uint64,
	minBefore uint64,
	prune func(before uint64) error,
) error

PrunePoolSnapshotsWithRetentionFloor is the snapshot manager's retention guard (wired via Manager.SetPoolSnapshotRetentionGuard). Under the deferred-header lock it evicts abandoned headers and computes the retention floor as ONE atomic decision, RELEASES the lock, and only then runs the caller's pool-snapshot prune. The prune must NOT run under the lock: it opens the single sqlite write connection (SetMaxOpenConns(1)) via Transaction(true), and block apply holds that connection before taking this same mutex through consumeDeferredHeaderValidation. Holding the mutex across prune therefore inverts the lock order (mutex→write-conn here vs. write-conn→mutex on apply) and deadlocks the node on the single write connection (issue #3717). Under the lock it, in order:

  1. Evicts abandoned deferred headers that are beyond the rollback horizon (tip minus the stability window). A canonical deferred header is consumed when the cursor applies it, so one still present that deep is on a fork chain selection can no longer re-adopt and would otherwise pin its snapshot forever (finding 5). The horizon — rather than the bare tip — is what makes eviction safe: eviction also drops the durable marker, and a point evicted while still re-adoptable would apply with required == false and skip its stateful header check. Eviction lets the floor rise; the evicted markers' persisted rows are deleted after the lock is released (best effort — they cannot affect a resolved header).
  2. Computes the retention floor over the surviving deferred headers and lowers defaultBefore (cleanup's currentEpoch-3 pool boundary) to it when a header needs an older snapshot (or to 0 = retain everything while any deferred slot is unmappable).
  3. Clamps the boundary UP to minBefore, a hard backstop (currentEpoch - poolSnapshotRetentionMaxDepth) that bounds how many historical epochs the pin can ever hold, so a stuck header cannot pin pool snapshots without limit (finding 5).

The eviction+floor read is atomic (one lock hold), so `before` reflects a coherent view of the deferred set; a header admitted after the lock is released — during or after prune — cannot corrupt this invocation's boundary. A header admitted in that window that needs a below-floor snapshot is a deeply lagged header (its need is < defaultBefore = currentEpoch-3); this invocation may prune a snapshot it wants, but the retention floor is a lower-watermark that is RE-COMPUTED every cleanup pass, so the next pass pins at the lower floor and the header resolves then. This narrow re-admit window is accepted in exchange for never inverting the lock order (issue #3717); it replaces the prior design that held the lock across prune and deadlocked.

prune must perform and COMMIT the pool-snapshot delete before returning; it must not touch ledger locks or the deferred set.

func (*LedgerState) Query

func (ls *LedgerState) Query(query any) (any, error)

func (*LedgerState) RecentChainPoints

func (ls *LedgerState) RecentChainPoints(
	count int,
) ([]ocommon.Point, error)

RecentChainPoints returns the requested count of recent chain points in descending order from the authoritative ledger tip. This avoids exposing blob-backed primary-chain points that have not yet been replayed into the metadata/ledger state.

func (*LedgerState) ReconcileLivePrimaryChainLedgerDivergence added in v0.47.1

func (ls *LedgerState) ReconcileLivePrimaryChainLedgerDivergence(
	reason string,
	connId ouroboros.ConnectionId,
) (bool, error)

ReconcileLivePrimaryChainLedgerDivergence is the exported entry point into the live-divergence reconciler. The plateau watchdog (internal/chainsyncrecycler) calls this when local tip has not advanced for plateau_duration while peers report a higher tip: if primary chain has advanced but the ledger pipeline is stuck on an abandoned same-slot fork, this rolls back the ledger to the latest common ancestor so forward application from the canonical chain can resume without a process or container restart. Returns (true, nil) when reconciliation happened, (false, nil) when no divergence was found.

reconcileLivePrimaryChainLedgerDivergence propagates ErrRollbackExceedsMithrilBoundary as a plain error, since its other two callers (handleEventChainsyncRollback, tryResolveFork -- both call it directly, not through this wrapper) classify and publish the matching resync themselves via handleMithrilBoundaryRollback, using peer-tip context this wrapper's only caller does not have. The plateau watchdog has no pending event batch or peer rollback handler of its own to classify this with, and chainsyncrecycler deliberately does not import ledger to inspect the error type (see that package's own doc comment), so this wrapper classifies and publishes it here instead, the same way reconcileLivePrimaryChainLedgerDivergence itself used to before that responsibility moved to each caller (wolf31o2, PR #3611).

func (*LedgerState) RecordForgedBlock added in v0.46.2

func (ls *LedgerState) RecordForgedBlock(
	block ledger.Block,
	blockCbor []byte,
	forgingLatency time.Duration,
)

RecordForgedBlock records observability for a block that this node successfully forged. Adoption into the local chain is tracked separately.

func (*LedgerState) RecoverAfterLocalRollback added in v0.27.7

func (ls *LedgerState) RecoverAfterLocalRollback(
	connIds []ouroboros.ConnectionId,
	point ocommon.Point,
) LocalRollbackRecoveryResult

RecoverAfterLocalRollback resets chainsync-local queued state after a ledger rollback, then replays any peer-local header history that still fits the new tip. This keeps rollback recovery local to the node instead of re-entering FindIntersect on live ChainSync sessions. The result reports whether peer history was replayed and whether connection closure should be skipped because the primary chain tip is already past the completed rollback point.

func (*LedgerState) RecoverCommitTimestampConflict added in v0.11.0

func (ls *LedgerState) RecoverCommitTimestampConflict() error

func (*LedgerState) SecurityParam added in v0.20.0

func (ls *LedgerState) SecurityParam() int

SecurityParam returns the security parameter for the current era. It takes a brief read lock around ls.currentEra, which ledgerProcessBlocks mutates under the write lock during epoch rollover/era transitions — reading it unlocked here raced with those writes (caught by -race in TestLiveTruncateUnderRealForgingAndNetworking, which runs real forging concurrently with the stall recycler's periodic SecurityParam() calls).

func (*LedgerState) SetEpochBoundarySnapshotHook added in v0.66.0

func (ls *LedgerState) SetEpochBoundarySnapshotHook(
	fn func(*database.Txn, event.EpochTransitionEvent) error,
)

SetEpochBoundarySnapshotHook installs (or clears, with a nil fn) the authoritative epoch-boundary snapshot capture. It is wired at node startup to the snapshot manager's CaptureEpochBoundarySnapshot before block sync begins. When no hook is set the ledger relies solely on the event-driven fallback capture, preserving the pre-wiring behavior.

func (*LedgerState) SetEpochBoundarySnapshotStakeHook added in v0.69.0

func (ls *LedgerState) SetEpochBoundarySnapshotStakeHook(
	fn func(*database.Txn, event.EpochTransitionEvent) error,
)

SetEpochBoundarySnapshotStakeHook installs (or clears, with a nil fn) the SNAP-point stake read of the authoritative epoch-boundary capture. It is wired at node startup to the snapshot manager's ComputeEpochBoundarySnapshot, alongside SetEpochBoundarySnapshotHook.

cardano-ledger runs SNAP before POOLREAP and before governance enactment, so the mark snapshot's stake must be read immediately after the delayed reward update and MIR — the boundary rules that precede SNAP — while the snapshot row itself can only be written at the end of the rollover, where the new epoch's nonce and the post-enactment protocol version exist. This hook is the read half; epochSnapshotHook is the write half. Both run in the same rollover transaction. With no stake hook installed the write half reads the stake itself using boundary-aware historical reconstruction.

func (*LedgerState) SetForgedBlockChecker added in v0.22.0

func (ls *LedgerState) SetForgedBlockChecker(checker ForgedBlockChecker)

SetForgedBlockChecker sets the forged block checker used for slot battle detection. This is typically called after the block forger is initialized, since the forger is created after the ledger state.

func (*LedgerState) SetForgingEnabled added in v0.22.0

func (ls *LedgerState) SetForgingEnabled(enabled bool)

SetForgingEnabled sets the forging_enabled metric gauge. Call with true after the block forger has been initialised successfully.

func (*LedgerState) SetMempool added in v0.14.0

func (ls *LedgerState) SetMempool(mempool MempoolProvider)

Sets the mempool for accessing transactions

func (*LedgerState) SetSlotBattleRecorder added in v0.22.0

func (ls *LedgerState) SetSlotBattleRecorder(
	recorder SlotBattleRecorder,
)

SetSlotBattleRecorder sets the recorder used to increment the slot battle metric. This is typically called after the block forger is initialized.

func (*LedgerState) SetTipForTesting added in v0.66.0

func (ls *LedgerState) SetTipForTesting(tip ochainsync.Tip)

SetTipForTesting replaces the in-memory tip and publishes a matching snapshot generation. It exists for black-box tests that cannot use the ledger package's white-box snapshot helpers.

func (*LedgerState) ShouldVerifyChainSelectionHeaderCrypto added in v0.70.3

func (ls *LedgerState) ShouldVerifyChainSelectionHeaderCrypto(
	slot uint64,
) bool

ShouldVerifyChainSelectionHeaderCrypto reports whether a header at the given slot is eligible to have its cryptography verified right now via ValidateChainSelectionHeaderCrypto. It mirrors the same exemptions the ledger's own chainsync header-queue path already applies (shouldVerifyChainsyncHeaderCrypto): verification is skipped while bulk historical/catch-up loading has not yet enabled live validation, and for slots already covered by an imported Mithril snapshot, since those slots were authenticated by the certificate chain during import and the restored database does not retain every historical epoch nonce. A caller that skips verification because this returns false must still treat the header as eligible, not reject it -- the same trust boundary the ledger's own pipeline already extends to this data.

func (*LedgerState) SlotToEpoch added in v0.6.0

func (ls *LedgerState) SlotToEpoch(slot uint64) (models.Epoch, error)

SlotToEpoch returns the epoch containing the given slot. See SlotTimeConverter.SlotToEpoch for details.

func (*LedgerState) SlotToTime added in v0.6.0

func (ls *LedgerState) SlotToTime(slot uint64) (time.Time, error)

SlotToTime returns the wall-clock start time of the given slot. See SlotTimeConverter.SlotToTime for details.

func (*LedgerState) SlotToTimeWithHorizonFrom added in v0.70.7

func (ls *LedgerState) SlotToTimeWithHorizonFrom(
	horizonAnchorSlot uint64,
	slot uint64,
) (time.Time, error)

SlotToTimeWithHorizonFrom returns the wall-clock start time of the given slot with the forecast horizon measured from horizonAnchorSlot. See SlotTimeConverter.SlotToTimeWithHorizonFrom.

func (*LedgerState) SlotsBehindHead added in v0.58.0

func (ls *LedgerState) SlotsBehindHead() uint64

SlotsBehindHead reports how many slots the applied ledger tip is behind the wall-clock head (0 if at or ahead of it, or if the wall slot is unknown). Unlike IsAtTip it distinguishes "chainsync reached the head" from "the ledger has actually applied up to the head", which matters during a from-scratch catch-up where the ledger replays a large backlog while chainsync is already at the head.

func (*LedgerState) SlotsPerEpoch added in v0.22.0

func (ls *LedgerState) SlotsPerEpoch() uint64

SlotsPerEpoch returns the number of slots in an epoch for the current era.

func (*LedgerState) SlotsPerKESPeriod added in v0.22.0

func (ls *LedgerState) SlotsPerKESPeriod() uint64

SlotsPerKESPeriod returns the number of slots in a KES period.

func (*LedgerState) StabilityWindow added in v0.39.0

func (ls *LedgerState) StabilityWindow() uint64

StabilityWindow returns the Ouroboros security stability window for the current era in slots. For Byron the window is 2k; for Shelley+ it is 3k/f. It is safe to call from multiple goroutines.

func (*LedgerState) Start added in v0.11.0

func (ls *LedgerState) Start(ctx context.Context) error

func (*LedgerState) SubmitAsyncDBOperation added in v0.19.0

func (ls *LedgerState) SubmitAsyncDBOperation(
	opFunc func(db *database.Database) error,
) error

SubmitAsyncDBOperation submits a database operation for execution on the worker pool. This method blocks waiting for the result and must be called after Start() and before Close(). If the worker pool is disabled, it falls back to synchronous execution.

func (*LedgerState) SubmitAsyncDBReadTxn added in v0.19.0

func (ls *LedgerState) SubmitAsyncDBReadTxn(
	opFunc func(txn *database.Txn) error,
) error

SubmitAsyncDBReadTxn submits a read-only database transaction operation for execution on the worker pool. This method blocks waiting for the result and must be called after Start() and before Close().

func (*LedgerState) SubmitAsyncDBTxn added in v0.19.0

func (ls *LedgerState) SubmitAsyncDBTxn(
	opFunc func(txn *database.Txn) error,
	readWrite bool,
) error

SubmitAsyncDBTxn submits a database transaction operation for execution on the worker pool. This method blocks waiting for the result and must be called after Start() and before Close(). If a partial commit occurs (blob committed but metadata failed), this method will attempt to trigger database recovery to restore consistency.

func (*LedgerState) SyncProgress added in v0.22.0

func (ls *LedgerState) SyncProgress() float64

SyncProgress returns the current sync progress as a value between 0.0 (unknown/just started) and 1.0 (fully synced), allowing the peer governor to exit bootstrap mode once sync reaches its threshold.

func (*LedgerState) SystemStart added in v0.21.0

func (ls *LedgerState) SystemStart() (time.Time, error)

It returns the system start timestamp from the Shelley genesis.

func (*LedgerState) TimeToSlot added in v0.6.0

func (ls *LedgerState) TimeToSlot(t time.Time) (uint64, error)

TimeToSlot returns the slot containing the given wall-clock time. See SlotTimeConverter.TimeToSlot for details.

func (*LedgerState) Tip

func (ls *LedgerState) Tip() ochainsync.Tip

Tip returns the current chain tip

func (*LedgerState) TransactionByHash added in v0.21.0

func (ls *LedgerState) TransactionByHash(
	hash []byte,
) (*models.Transaction, error)

TransactionByHash returns a transaction record by its hash.

func (*LedgerState) UpstreamSyncStatus added in v0.70.3

func (ls *LedgerState) UpstreamSyncStatus() (uint64, bool)

UpstreamSyncStatus reports whether a live upstream is selected and its corroborated target. An active upstream with target 0 is still syncing.

func (*LedgerState) UpstreamTipSlot added in v0.22.0

func (ls *LedgerState) UpstreamTipSlot() uint64

UpstreamTipSlot returns the corroborated remote sync target while an upstream connection is active. The admitted frontier is retained separately for admission bookkeeping.

func (*LedgerState) UtxoByRef

func (ls *LedgerState) UtxoByRef(
	txId []byte,
	outputIdx uint32,
) (*models.Utxo, error)

UtxoByRef returns a single UTxO by reference

func (*LedgerState) UtxoByRefIncludingSpent added in v0.22.0

func (ls *LedgerState) UtxoByRefIncludingSpent(
	txId []byte,
	outputIdx uint32,
) (*models.Utxo, error)

UtxoByRefIncludingSpent returns a UTxO by reference, including spent outputs. This is needed for APIs that must resolve consumed inputs to display source address and amount.

func (*LedgerState) UtxosByAddress

func (ls *LedgerState) UtxosByAddress(
	addrs []ledger.Address,
) ([]models.Utxo, error)

UtxosByAddress returns all UTxOs that belong to any of the specified addresses

func (*LedgerState) UtxosByAddressAtSlot added in v0.22.0

func (ls *LedgerState) UtxosByAddressAtSlot(
	addr lcommon.Address,
	slot uint64,
) ([]models.Utxo, error)

UtxosByAddressAtSlot returns all UTxOs belonging to the specified address that existed at the given slot.

func (*LedgerState) UtxosByAddressWithOrdering added in v0.27.5

func (ls *LedgerState) UtxosByAddressWithOrdering(
	q *models.UtxoWithOrderingQuery,
) ([]models.UtxoWithOrdering, error)

UtxosByAddressWithOrdering returns UTxOs matching q with ordering metadata. See models.UtxoWithOrderingQuery (nil SearchUtxos predicate: MatchAllAddresses).

func (*LedgerState) UtxosByRefs added in v0.70.0

func (ls *LedgerState) UtxosByRefs(
	refs []models.UtxoId,
) ([]models.Utxo, error)

UtxosByRefs returns the live UTxOs matching the given references in a single batch. Refs with no matching live UTxO are simply absent from the result.

func (*LedgerState) ValidateBlockHeaderCrypto added in v0.69.0

func (ls *LedgerState) ValidateBlockHeaderCrypto(
	header ledger.BlockHeader,
) error

ValidateBlockHeaderCrypto validates a header using the current ledger state. It is used by protocol handlers that receive a header without its block body (for example LeiosNotify announcements) and must not let an unauthenticated header influence shared state.

func (*LedgerState) ValidateChainSelectionHeaderCrypto added in v0.70.3

func (ls *LedgerState) ValidateChainSelectionHeaderCrypto(
	header ledger.BlockHeader,
) error

ValidateChainSelectionHeaderCrypto verifies a header's VRF/KES cryptography and, where the local ledger's stake/pool state has already caught up to the header's epoch, its leader eligibility. It lets chain selection require that a peer-reported header has passed the same checks as the applied chain before the header is allowed to influence Genesis density or corroboration (dingo #3517), independent of whether that header will ever be applied to the ledger.

It never advances the shared epoch cache (matching ValidateBlockHeaderCrypto's no-mutation contract for header-only validation), but unlike ValidateBlockHeaderCrypto it tolerates ledger state that has not yet caught up to the header's slot: that is the normal condition for a peer legitimately racing ahead of local ledger application during fast sync or Genesis bootstrap. Use IsHeaderVerificationDeferred to distinguish that case (the header must still be treated as eligible) from a header this node can already prove is invalid.

func (*LedgerState) ValidateForgedBlock added in v0.58.0

func (ls *LedgerState) ValidateForgedBlock(
	block ledger.Block,
	_ []byte,
) error

ValidateForgedBlock validates a locally-forged block before it is adopted onto the chain and diffused to peers. It runs three checks in order:

  1. Header crypto — VRF proof and KES signature verification (skipped for Byron-era blocks which use PBFT consensus and have no VRF/KES fields).
  2. Body-hash consistency — verifies that the body hash in the header is non-zero, catching any builder bug that would embed an all-zero hash.
  3. Per-transaction ledger rules — each transaction in the block is validated against the current UTxO state. An intra-block overlay is maintained so that transactions spending outputs created earlier in the same block are correctly resolved.

A non-nil error means the block is invalid and must not be adopted or diffused. This function satisfies the forging.BlockValidator interface.

func (*LedgerState) ValidateLeiosAnnouncementHeader added in v0.70.2

func (ls *LedgerState) ValidateLeiosAnnouncementHeader(
	header ledger.BlockHeader,
) (LeiosAnnouncementOCINStaleness, error)

ValidateLeiosAnnouncementHeader validates the announcement's header crypto before classifying its op-cert counter against the selected primary chain's immutable-tip state. Counter equality and arbitrary forward movement are fresh because this lagging view cannot enforce an upper bound. A lower or as-yet-unknown counter is stale, not invalid.

The result is deliberately a ledger verdict only. The Ouroboros composition layer owns whether a stale peer message is recorded, published, or relayed.

func (*LedgerState) ValidateTx

func (ls *LedgerState) ValidateTx(
	tx lcommon.Transaction,
) error

ValidateTx runs ledger validation on the provided transaction. It accepts transactions from the current era and the immediately previous era (era-1), as Cardano allows during the overlap period after a hard fork.

func (*LedgerState) ValidateTxWithOverlay added in v0.23.0

func (ls *LedgerState) ValidateTxWithOverlay(
	tx lcommon.Transaction,
	consumedUtxos map[string]struct{},
	createdUtxos map[string]lcommon.Utxo,
) error

ValidateTxWithOverlay runs ledger validation with a UTxO overlay from pending mempool transactions. consumedUtxos contains inputs already spent by pending TXs (double-spend check), createdUtxos contains outputs created by pending TXs (dependent TX chaining). Both may be nil for no overlay.

func (*LedgerState) WithTxValidationSession added in v0.69.0

func (ls *LedgerState) WithTxValidationSession(
	fn func(
		validate func(
			tx ledger.Transaction,
			consumedUtxos map[string]struct{},
			createdUtxos map[string]lcommon.Utxo,
		) error,
		stillCurrent func() bool,
	) error,
) error

WithTxValidationSession pins a mempool revalidation batch to one immutable ledger publication, one validation slot/era/parameter set, and one repeatable-read database transaction. stillCurrent lets the mempool reject the candidate immediately before its atomic swap if a block or rollback published a newer generation while validation was running.

type LedgerStateConfig

type LedgerStateConfig struct {
	PromRegistry      prometheus.Registerer
	Logger            *slog.Logger
	Database          *database.Database
	ChainManager      *chain.ChainManager
	EventBus          *event.EventBus
	CardanoNodeConfig *cardano.CardanoNodeConfig
	// Network is the CLI/YAML/env network selector dingo was started with
	// (e.g. "mainnet", "preprod", "prime-mainnet"). Shelley genesis alone
	// cannot distinguish real Cardano mainnet from a foreign chain that
	// reuses its identity for wire compatibility -- see isMainnet in
	// header_protocol_version.go. Empty when dingo was configured with a
	// raw NetworkMagic instead of a named network.
	Network                     string
	BlockfetchRequestRangeFunc  BlockfetchRequestRangeFunc
	PeersWithBlockFunc          PeersWithBlockFunc
	RecordBlockfetchLatencyFunc RecordBlockfetchLatencyFunc
	BlockfetchLatencyFunc       BlockfetchLatencyFunc
	BlockfetchLatencyMedianFunc BlockfetchLatencyMedianFunc
	GetActiveConnectionFunc     GetActiveConnectionFunc
	GetPeerObservedTipFunc      GetPeerObservedTipFunc
	GetPeerSyncTargetFunc       GetPeerSyncTargetFunc
	ConnectionLiveFunc          ConnectionLiveFunc
	ConnectionSwitchFunc        ConnectionSwitchFunc
	ClearSeenHeadersFromFunc    ClearSeenHeadersFromFunc
	PeerHeaderLookupFunc        PeerHeaderLookupFunc
	GenesisSelectionStateFunc   GenesisSelectionStateFunc
	FatalErrorFunc              FatalErrorFunc
	ForgedBlockChecker          ForgedBlockChecker
	SlotBattleRecorder          SlotBattleRecorder
	EndorserBlockProvider       EndorserBlockProviderFunc
	// EndorserBlockFetcher actively fetches a referenced endorser block (its
	// manifest and all transaction bodies) by point and caches it, so the
	// EndorserBlockProvider can then supply it. Unlike the tip path, which waits
	// for the relay to diffuse an endorser block it is already pushing, this is
	// used during historical catch-up: the prototype relay serves any endorser
	// block by point on demand (MsgLeiosBlockRequest), so the node can backfill
	// the endorser-resident outputs of older ranking blocks instead of trusting
	// the chain and leaving the UTxO set incomplete. Nil disables backfill.
	EndorserBlockFetcher EndorserBlockFetcherFunc
	// EndorserBlockWaitSlots is the number of slots that block processing
	// waits at the chain tip for a Dijkstra ranking block's referenced
	// endorser block to finish fetching before applying it. It is sourced from
	// the Leios pipeline timing (CertifyByDeadlineSlots, not the shorter
	// DiffuseWindowSlots: by the time a ranking block references an endorser
	// block that block has already been certified, so the certify-by deadline
	// is the bound for when it is actually available to fetch) rather than a
	// hardcoded duration; the ledger converts it to wall-clock using the
	// Shelley slot length. Zero disables best-effort announcement waiting, but
	// does not permit a Musashi certifying ranking block to commit without its
	// certified closure.
	EndorserBlockWaitSlots uint64
	// LeiosApplyEndorserBlockTxs selects the endorser-block ledger path. When
	// true (the CIP-conformant path, dingo's forward behavior for real Leios),
	// a referenced endorser block's transactions are applied to the UTxO set.
	// When false (the Haskell-conformant path, matching prototype-2026w29), only
	// the certified parent announcement is applied, with full effects but without
	// validation or consumed-input recovery. Set from the network in node.go
	// (false on musashi, true otherwise).
	LeiosApplyEndorserBlockTxs bool
	// SkipLeaderStakeThresholdCheck, when true, downgrades a failed Praos
	// stake-derived leader-eligibility check from a hard header rejection to a
	// logged warning (the block is trusted). It defaults to false so the check
	// is enforced everywhere unless explicitly disabled.
	//
	// dingo derives a pool's leadership stake from delegated UTxO only; it does
	// not yet compute staking rewards (CalculateRewards/GetAdaPots/
	// RewardAccountBalance are unimplemented), so reward-account balances are
	// omitted from the stake distribution. On real networks (many diffuse
	// pools) this omission is proportionally negligible and the check catches
	// genuine ineligibility, so it stays enforced. On the concentrated
	// prototype-2026w29 musashi topology the dominant pool's reward accrual
	// drifts its true relative stake above the UTxO-only figure, so enforcing
	// the threshold falsely rejects that pool's legitimately-eligible blocks and
	// wedges the chain — so it is skipped there. All other header checks (KES,
	// VRF proof, registered-VRF-key binding, opcert) still apply regardless.
	// Separately, TPraos bootstrap epochs with decentralization still active
	// validate genesis overlay assignment in verify_header.go, then skip only
	// the local pool stake-threshold check while d remains active.
	// Interim measure until reward calculation lands and reward balances can be
	// included in the leadership stake. Set from the network in node.go (true
	// on musashi, false otherwise) via Config.prototypeTrustBypassesEnabled,
	// which requires an unambiguous Musashi identity so this can never be
	// reached from a preview/preprod/mainnet configuration.
	SkipLeaderStakeThresholdCheck bool
	// SkipDijkstraTxValidation, when true, skips the Dijkstra per-transaction
	// validation rule set entirely. On the Haskell-conformant Musashi path,
	// certified closure and ranking-block transactions are trusted because the
	// prototype does not validate endorser-block transactions. Running dingo's
	// rule set only to discard any disagreement is
	// wasted work that prevents the node from reaching tip under load. Set true
	// on Musashi in node.go via Config.prototypeTrustBypassesEnabled, which
	// requires an unambiguous Musashi identity so this can never be reached
	// from a preview/preprod/mainnet configuration. Applies to Dijkstra-era
	// transactions only — see LedgerState.skipDijkstraTxValidation. Interim
	// until the Leios certificate / endorser-availability surface is complete
	// (#2587).
	SkipDijkstraTxValidation bool
	// MinPoolMargin is the CIP-23 minimum pool margin (minimum variable fee) in
	// basis points, [0, 10000] (150 = 1.5%); 0 disables it. It is a consensus-
	// affecting operator setting (not derived from the network) that takes
	// effect only in Dijkstra and later. Enable a nonzero value only on a
	// network where every node also enables the same value.
	MinPoolMargin uint
	// PledgeLeverageEnabled turns on the CIP-50 pledge-leverage reward cap. It
	// is a consensus-affecting feature gate that defaults false; enable it only
	// on a network where every node also enables it (mainnet and the public
	// testnets keep it off). Unlike the Musashi-derived toggles above it is set
	// from operator config in node.go, not derived from the network.
	PledgeLeverageEnabled bool
	// PledgeLeverage is L, the CIP-50 maximum ratio of total stake to pledge,
	// in the range [1, 10000]. It is used only when PledgeLeverageEnabled is
	// true.
	PledgeLeverage uint
	// FullPotRewardsEnabled turns on CIP-0163 full-pot reward distribution: the
	// entire epoch reward pot is apportioned across pools that earned a base
	// reward instead of returning the saturation/pledge/performance residual to
	// reserves. It is a consensus-affecting feature gate that defaults false;
	// enable it only on a network where every node also enables it (mainnet and
	// the public testnets keep it off). Like the CIP-50 pledge-leverage gate it
	// is set from operator config in node.go, not derived from the network.
	FullPotRewardsEnabled bool
	// DelegatorInactivityEnabled turns on CIP-0163 reward-account inactivity
	// expiry. Consensus-affecting; defaults false. Set from operator config in
	// node.go (serve mode) and internal/node/load.go (load/replay mode), not
	// derived from the network. Must match across the network.
	DelegatorInactivityEnabled bool
	// DelegatorInactivity is the inactivity window in epochs, used only when
	// DelegatorInactivityEnabled is true.
	DelegatorInactivity      uint64
	ValidateHistorical       bool
	EnableDijkstra           bool
	StartInDijkstra          bool
	TrustedReplay            bool
	ManualBlockProcessing    bool
	ForgeBlocks              bool
	DatabaseWorkerPoolConfig DatabaseWorkerPoolConfig
	// BlockPipelineEnabled turns on parallel block decode in the chainsync
	// replay loop (ledgerReadChainIterator): blocks read back from the
	// primary chain are decoded by a small worker pool (gouroboros'
	// pipeline package) instead of one at a time inline, then re-sequenced
	// before being handed to ledgerProcessBlocksFromSource exactly as
	// today. Validation and apply are untouched -- this only changes how
	// CBOR decode work is scheduled. Off by default: throughput and
	// stability are still being proven (issue #1894 phase 1). See
	// ARCHITECTURE.md ("Block Processing Pipeline").
	//
	// A rollback drains blockPipeline's in-flight decode/validate backlog
	// (drainBlockPipelineBeforeRollback, issue #1894 phase 5) before it
	// proceeds, to shrink -- not eliminate -- the window in which an
	// already-in-flight batch from an abandoned fork could otherwise be
	// applied after the rollback. See ARCHITECTURE.md ("Phase 5: rollback
	// coordination").
	BlockPipelineEnabled bool
	// BlockPipelineValidateEnabled adds parallel VRF/KES validation to the
	// decode pipeline (issue #1894 phase 3). Dingo supplements the generic
	// stage with the OpCert cold-key signature and MaxKESEvolutions checks,
	// and enforces results only where the serial path has validation state:
	// not trusted historical/Mithril replay and only with a cached epoch
	// nonce. A rejection is returned as headerValidationError so the already-
	// persisted chain can be rewound rather than retried forever.
	//
	// This is defense in depth, not a replacement for admission validation.
	// Headers and blocks remain fully checked before entering ls.chain because
	// that chain is served to downstream clients before ledger apply. See
	// ARCHITECTURE.md ("Block Processing Pipeline").
	//
	// This flag's extra CPU cost (two dedicated VRF/KES workers) can make
	// block-apply throughput fall behind header arrival during bursty
	// near-tip conditions more easily than decode-only phase 1 or the
	// pre-pipeline baseline hit in practice; if that happens for long
	// enough, the chain's queued-header backlog can reach capacity while a
	// fork is being resolved. tryResolveFork's failure handling used to
	// silently strand that backlog in exactly that case, stalling sync
	// with no error logged above WARN until chainsyncrecycler's
	// local-tip-plateau watchdog eventually forced a resync (~20 minutes
	// with default config) -- this was a general, pre-existing gap in
	// tryResolveFork, not specific to this flag (reproduced live under
	// this flag, under decode-only, and under the pre-pipeline baseline
	// alike); the flag's throughput cost just makes it easier to reach.
	// See ensureBlockfetchDrainingAfterForkQueueFailure and
	// ARCHITECTURE.md ("Fork-resolution header-queue overflow must still
	// restart blockfetch") for the fix and the full explanation.
	BlockPipelineValidateEnabled bool
}

type LedgerView

type LedgerView struct {
	// contains filtered or unexported fields
}

func (*LedgerView) ByronProtocolMagic added in v0.70.0

func (lv *LedgerView) ByronProtocolMagic() (uint32, error)

func (*LedgerView) CalculateRewards added in v0.18.0

func (lv *LedgerView) CalculateRewards(
	adaPots lcommon.AdaPots,
	rewardSnapshot lcommon.RewardSnapshot,
	rewardParams lcommon.RewardParameters,
) (*lcommon.RewardCalculationResult, error)

CalculateRewards calculates rewards for the given stake keys. TODO: implement reward calculation. Requires reward formulas from the Cardano Shelley formal specification and integration with stake snapshots.

func (*LedgerView) CommitteeCredentialMember added in v0.70.5

func (lv *LedgerView) CommitteeCredentialMember(
	coldCredential lcommon.Credential,
) (*lcommon.CommitteeMember, error)

CommitteeCredentialMember resolves a seated or pending proposed committee member by full tagged cold credential identity.

func (*LedgerView) CommitteeHotCredentialMember added in v0.70.5

func (lv *LedgerView) CommitteeHotCredentialMember(
	hotCredential lcommon.Credential,
) (*lcommon.CommitteeMember, error)

CommitteeHotCredentialMember resolves a committee authorization by exact tagged hot credential identity.

Deliberately not filtered by term expiry. The Conway GOV rule resolves a committee voter against the authorization map, which excludes only resigned members, and its protocol-version-11 elected-voter gate intersects committee membership by cold credential alone. Expiry is applied later, in the RATIFY tally and in the committeeMinSize active count, so skipping an expired member here would raise UnknownVoterError on a vote cardano-ledger accepts. A resigned member is excluded, matching the upstream authorization set.

func (*LedgerView) CommitteeMember added in v0.21.0

func (lv *LedgerView) CommitteeMember(
	coldKey lcommon.Blake2b224,
) (*lcommon.CommitteeMember, error)

CommitteeMember preserves the legacy hash-only contract. It returns nil when key and script credentials with the same hash are both members rather than choosing one by iteration order.

func (*LedgerView) CommitteeMembers added in v0.21.0

func (lv *LedgerView) CommitteeMembers() ([]lcommon.CommitteeMember, error)

CommitteeMembers returns all seated committee members.

Resolution runs off the single GetCommitteeMembers load rather than calling CommitteeCredentialMember per seat, which would reload the whole set for every member. Resignations are fetched for the whole set in one query.

func (*LedgerView) CommitteeStateAvailable added in v0.70.5

func (lv *LedgerView) CommitteeStateAvailable() (bool, error)

CommitteeStateAvailable reports whether this view can authoritatively answer committee credential queries for its snapshot.

Availability is derived from whether a committee was ever seated, not from the store being reachable and not from the currently seated set. Only two paths ever write committee_member: UpdateCommittee enactment (ledger/governance/enact.go) and Mithril snapshot import (ledgerstate/import.go). Dingo does not seed the Conway genesis committee -- genesis.Committee.Threshold is read for the CC quorum, but genesis.Committee.Members is never persisted (blinklabs-io/dingo#3785). A node synced from genesis therefore holds no committee rows at all for the whole Conway era until the first UpdateCommittee enacts, while the real chain has the genesis committee seated from the hard fork. Claiming authority there would reject an authorization from a real committee member, because the lookup returns no member.

Removal is a soft delete: both SoftDeleteAllCommitteeMembers on NoConfidence and SoftDeleteCommitteeMembers on UpdateCommittee removal set deleted_slot and leave the row. So the include-deleted set separates the two empty states exactly. No rows at all means never populated, which is the genesis-synced ambiguity and reports false. Rows that are all soft-deleted mean the committee was seated and is now authoritatively empty, which reports true so a former member's authorization or resignation fails closed, as the real chain rejects it.

Once #3785 lands, the no-rows case becomes unambiguously authoritative too and this can report true unconditionally.

func (*LedgerView) Constitution added in v0.21.0

func (lv *LedgerView) Constitution() (*lcommon.Constitution, error)

Constitution returns the enacted constitution: its anchor URL, anchor hash, and optional guardrails policy hash.

Constitution state that is missing or malformed fails closed with governance.ErrConstitutionUnavailable; a constitution store that cannot be read at all returns the wrapped store error. Neither reports an empty-but-valid constitution, which gouroboros' guardrails rule would read as "no guardrails script required".

func (*LedgerView) CostModels added in v0.21.0

func (lv *LedgerView) CostModels() map[lcommon.PlutusLanguage]lcommon.CostModel

CostModels returns which Plutus language versions have cost models defined in the current protocol parameters.

NOTE: lcommon.CostModel is currently struct{} in gouroboros (a placeholder type). The returned map values carry no cost parameter data -- callers use map membership to check version availability. When gouroboros extends CostModel with real fields, this function should be updated to populate them from the raw []int64 cost parameters.

Map keys use PlutusLanguage encoding: PlutusV1=1, PlutusV2=2, PlutusV3=3, corresponding to cost model map keys 0, 1, 2.

func (*LedgerView) DRepDelegation added in v0.67.0

func (lv *LedgerView) DRepDelegation(
	cred lcommon.Credential,
) (*lcommon.Drep, error)

DRepDelegation returns the DRep that the given stake credential is vote-delegated to, or nil when the credential is not registered or is not delegated to any DRep. It satisfies gouroboros' common.DRepDelegationState, which the ledger rules use to validate reward withdrawals on protocol versions 10 and 11 (a withdrawal from a credential not delegated to a DRep is rejected).

func (*LedgerView) DRepRegistration added in v0.21.0

func (lv *LedgerView) DRepRegistration(
	credential lcommon.Blake2b224,
) (*lcommon.DRepRegistration, error)

DRepRegistration returns a DRep registration by credential. Returns nil if the credential is not registered as an active DRep.

func (*LedgerView) DRepRegistrations added in v0.21.0

func (lv *LedgerView) DRepRegistrations() ([]lcommon.DRepRegistration, error)

DRepRegistrations returns all active DRep registrations.

func (*LedgerView) EpochForSlot added in v0.70.7

func (lv *LedgerView) EpochForSlot(slot uint64) (uint64, error)

EpochForSlot returns the epoch containing the given slot, satisfying gouroboros' optional common.EpochState capability.

Several ledger rules are expressed relative to the current epoch and degrade to a weaker check when the ledger state cannot supply one. Without this the pool-deposit decision cannot tell a retired pool from a registered one, so a registration for an already-retired pool is charged no deposit and the transaction fails value conservation by exactly that amount (issue #3908); the retirement-epoch bound on pool retirement certificates is skipped for the same reason.

func (*LedgerView) GetAdaPots added in v0.18.0

func (lv *LedgerView) GetAdaPots() lcommon.AdaPots

GetAdaPots returns the current Ada pots. TODO: implement the complete Ada pots retrieval. Treasury and reserves are tracked in network_state, but this interface also needs the current fee and reward pots as one coherent validation snapshot.

func (*LedgerView) GetAdaPotsWithError added in v0.49.0

func (lv *LedgerView) GetAdaPotsWithError() (lcommon.AdaPots, error)

GetAdaPotsWithError returns the current Ada pots.

func (*LedgerView) GetCommitteeActiveCount added in v0.22.0

func (lv *LedgerView) GetCommitteeActiveCount() (int, error)

GetCommitteeActiveCount returns the number of active (non-resigned) committee members.

func (*LedgerView) GetDRepVotingPower added in v0.22.0

func (lv *LedgerView) GetDRepVotingPower(
	credentialTag uint8,
	drepCredential []byte,
) (uint64, error)

GetDRepVotingPower returns the voting power for a DRep by summing the current stake of all delegated accounts, approximated from live UTxO balance plus reward-account balance.

TODO: Accept an epoch parameter and use epoch-based stake snapshots for accurate voting power. The current implementation approximates voting power using current live balances.

func (*LedgerView) GetExpiredDReps added in v0.22.0

func (lv *LedgerView) GetExpiredDReps(
	epoch uint64,
) ([]*models.Drep, error)

GetExpiredDReps returns all active DReps whose expiry epoch is at or before the given epoch.

func (*LedgerView) GetLeiosKeys added in v0.70.0

func (lv *LedgerView) GetLeiosKeys(
	epoch uint64,
	poolKeyHashes []lcommon.PoolKeyHash,
) (map[string]*lcommon.LeiosKey, error)

GetLeiosKeys returns the Dijkstra/Leios BLS key frozen with each named pool's Mark stake snapshot for epoch. A pool absent from the result has no captured key. The returned keys are raw; callers must verify proof of possession before treating a key as usable.

func (*LedgerView) GetPoolStake added in v0.22.0

func (lv *LedgerView) GetPoolStake(
	epoch uint64,
	poolKeyHash []byte,
) (uint64, error)

GetPoolStake returns the stake for a specific pool from the snapshot. Returns 0 if the pool has no stake in the snapshot.

func (*LedgerView) GetRewardSnapshot added in v0.18.0

func (lv *LedgerView) GetRewardSnapshot(
	epoch uint64,
) (lcommon.RewardSnapshot, error)

GetRewardSnapshot returns the current reward snapshot. TODO: implement reward snapshot retrieval. Requires per-stake-credential reward tracking which is not yet stored in the database.

func (*LedgerView) GetStakeDistribution added in v0.22.0

func (lv *LedgerView) GetStakeDistribution(
	epoch uint64,
) (*StakeDistribution, error)

GetStakeDistribution returns the mark stake distribution at the requested snapshot epoch. Callers choose the Praos-active epoch before calling.

func (*LedgerView) GetTotalActiveStake added in v0.22.0

func (lv *LedgerView) GetTotalActiveStake(epoch uint64) (uint64, error)

GetTotalActiveStake returns the total stake from the requested mark snapshot.

func (*LedgerView) GovActionById added in v0.21.0

func (lv *LedgerView) GovActionById(
	id lcommon.GovActionId,
) (*lcommon.GovActionState, error)

GovActionById returns a governance action by its ID. Returns nil if the governance action does not exist.

func (*LedgerView) GovActionExists added in v0.21.0

func (lv *LedgerView) GovActionExists(id lcommon.GovActionId) bool

GovActionExists returns whether a governance action exists.

func (*LedgerView) GovPurposeRoots added in v0.70.1

func (lv *LedgerView) GovPurposeRoots() (*lcommon.GovPurposeRoots, error)

GovPurposeRoots returns the latest enacted action for each CIP-1694 governance purpose. A non-nil result with nil fields means Dingo has authoritatively determined that the corresponding purpose has no root.

func (*LedgerView) IsPoolRegistered added in v0.21.0

func (lv *LedgerView) IsPoolRegistered(pkh lcommon.PoolKeyHash) bool

IsPoolRegistered checks if a pool is currently registered

func (*LedgerView) IsRewardAccountRegistered added in v0.21.0

func (lv *LedgerView) IsRewardAccountRegistered(
	cred lcommon.Credential,
) bool

IsRewardAccountRegistered checks if a reward account is registered

func (*LedgerView) IsStakeCredentialRegistered added in v0.21.0

func (lv *LedgerView) IsStakeCredentialRegistered(
	cred lcommon.Credential,
) bool

IsStakeCredentialRegistered checks if a stake credential is currently registered

func (*LedgerView) IsVrfKeyInUse added in v0.22.0

func (lv *LedgerView) IsVrfKeyInUse(
	vrfKeyHash lcommon.Blake2b256,
) (bool, lcommon.PoolKeyHash, error)

IsVrfKeyInUse checks if a VRF key hash is registered by another pool. Returns (inUse, owningPoolId, error).

func (*LedgerView) MinPoolMargin added in v0.67.0

func (lv *LedgerView) MinPoolMargin() *big.Rat

MinPoolMargin forwards the CIP-23 minimum pool margin from the underlying ledger state so that a *LedgerView (the value passed to ValidateTx*) satisfies the eras.MinPoolMarginProvider interface. Without this, the Dijkstra pool-margin-floor certificate rule would never see the configured floor.

func (*LedgerView) NetworkId

func (lv *LedgerView) NetworkId() uint

func (*LedgerView) PoolCurrentState added in v0.17.0

func (lv *LedgerView) PoolCurrentState(
	pkh lcommon.PoolKeyHash,
) (*lcommon.PoolRegistrationCertificate, *uint64, error)

It returns the most recent active pool registration certificate and the epoch of any pending retirement for the given pool key hash.

func (*LedgerView) PoolRegistration

func (lv *LedgerView) PoolRegistration(
	pkh lcommon.PoolKeyHash,
) ([]lcommon.PoolRegistrationCertificate, error)

func (*LedgerView) RewardAccountBalance added in v0.21.0

func (lv *LedgerView) RewardAccountBalance(
	cred lcommon.Credential,
) (*uint64, error)

RewardAccountBalance returns the current reward balance for a stake credential. Missing and inactive reward accounts are represented by a nil balance, as required by the gouroboros reward-state contract. A registered account with a zero balance returns a non-nil pointer to zero.

func (*LedgerView) SkipPhase2Validation added in v0.50.0

func (lv *LedgerView) SkipPhase2Validation() bool

func (*LedgerView) SlotToTime added in v0.17.0

func (lv *LedgerView) SlotToTime(slot uint64) (time.Time, error)

SlotToTime returns the current time for a given slot based on known epochs.

This is the converter transaction validation sees, and a Plutus script context must convert the transaction's validity interval through it. The forecast horizon stays in force, matching cardano-ledger's TimeTranslationPastHorizon failure, but it is measured from this view's horizon anchor so a block being applied is judged against its own predecessor rather than a tip that has not been published yet (issue #3844).

func (*LedgerView) StakeCredentialDeposit added in v0.70.4

func (lv *LedgerView) StakeCredentialDeposit(
	cred lcommon.Credential,
) (*uint64, error)

StakeCredentialDeposit returns the registration deposit currently held for a registered stake credential. The account lookup preserves the live registration semantics used by IsStakeCredentialRegistered, while the registration history carries the deposit actually paid rather than the current protocol-parameter value.

func (*LedgerView) StakeRegistration

func (lv *LedgerView) StakeRegistration(
	stakingKey []byte,
) ([]lcommon.StakeRegistrationCertificate, error)

func (*LedgerView) StakeRegistrationByCredential added in v0.55.0

func (lv *LedgerView) StakeRegistrationByCredential(
	cred lcommon.Credential,
) ([]lcommon.StakeRegistrationCertificate, error)

StakeRegistrationByCredential returns stake registration certificates for the full stake credential identity, preserving key/script credential separation.

func (*LedgerView) TimeToSlot added in v0.17.0

func (lv *LedgerView) TimeToSlot(t time.Time) (uint64, error)

TimeToSlot returns the slot number for a given time based on known epochs

func (*LedgerView) TreasuryValue added in v0.21.0

func (lv *LedgerView) TreasuryValue() (uint64, error)

TreasuryValue returns the treasury value visible to this ledger view. A view used for transaction validation carries the same database transaction as the rest of that validation, so epoch-boundary pot changes and rollback are read from one atomic ledger snapshot.

func (*LedgerView) UpdateAdaPots added in v0.18.0

func (lv *LedgerView) UpdateAdaPots(adaPots lcommon.AdaPots) error

UpdateAdaPots updates the Ada pots. TODO: implement Ada pots update. Requires Ada pots storage in the database.

func (*LedgerView) UtxoById

func (lv *LedgerView) UtxoById(
	utxoId lcommon.TransactionInput,
) (lcommon.Utxo, error)

type LeiosAnnouncementOCINStaleness added in v0.70.2

type LeiosAnnouncementOCINStaleness uint8

LeiosAnnouncementOCINStaleness reports whether an otherwise-valid dangling Leios announcement uses an operational-certificate issue number accepted by the chain-dependent state at the immutable tip.

const (
	// LeiosAnnouncementFreshOCIN means the announcement counter is equal to or
	// ahead of the immutable-tip counter and may be processed and relayed.
	LeiosAnnouncementFreshOCIN LeiosAnnouncementOCINStaleness = iota
	// LeiosAnnouncementStaleOCIN means the announcement counter is lower than
	// the immutable-tip counter, or its issuer is unknown at that point. The
	// peer message is accepted, but networking must not process or relay it.
	LeiosAnnouncementStaleOCIN
)

type LocalRollbackRecoveryResult added in v0.31.1

type LocalRollbackRecoveryResult struct {
	Recovered           bool
	SkipConnectionClose bool
	PrimaryChainTipSlot uint64
}

type LocalStateQueryLimitError added in v0.70.6

type LocalStateQueryLimitError struct {
	QueryName               string
	SubmittedItemCount      int
	MaximumAllowedItemCount int
}

LocalStateQueryLimitError describes an over-limit LocalStateQuery request. In-process callers can use errors.Is for the stable category and errors.As for QueryName, SubmittedItemCount, and MaximumAllowedItemCount. Node-to-client protocol errors terminate the connection, so an over-the-wire client observes a closed connection rather than this Go error value.

func (*LocalStateQueryLimitError) Error added in v0.70.6

func (e *LocalStateQueryLimitError) Error() string

func (*LocalStateQueryLimitError) Unwrap added in v0.70.6

func (e *LocalStateQueryLimitError) Unwrap() error

type MempoolProvider added in v0.14.0

type MempoolProvider interface {
	Transactions() []PendingTransaction
	// RemoveTxsByHash removes confirmed transactions without cascading to
	// chained descendants, which remain valid against the updated ledger.
	RemoveTxsByHash(hashes []string)
}

MempoolProvider provides pending transactions without exposing mempool DTOs.

type PeerHeaderLookupFunc added in v0.27.7

type PeerHeaderLookupFunc func(
	connId ouroboros.ConnectionId,
	hash []byte,
) (ChainsyncEvent, []byte, bool)

PeerHeaderLookupFunc looks up a previously observed header for a peer connection, even if that header was suppressed before entering the ledger queue. It returns the recorded chainsync event, the header's prev-hash, and whether the header was found.

type PeersWithBlockFunc added in v0.38.0

type PeersWithBlockFunc func(
	origin ouroboros.ConnectionId,
	point ocommon.Point,
) []ouroboros.ConnectionId

PeersWithBlockFunc returns all tracked connection IDs — excluding origin — that have a recorded observed header at the given point. Used to locate shadow peers for parallel blockfetch dispatch.

type PendingTransaction added in v0.55.0

type PendingTransaction struct {
	Hash string
	Cbor []byte
	Type uint
}

PendingTransaction is the transaction view ledger block construction needs.

type PoolRelay added in v0.55.0

type PoolRelay struct {
	Hostname string
	IPv4     *net.IP
	IPv6     *net.IP
	Port     uint
}

PoolRelay represents a stake pool relay as exposed by the ledger/database boundary.

type PoolRelayProvider added in v0.55.0

type PoolRelayProvider struct {
	// contains filtered or unexported fields
}

PoolRelayProvider exposes active stake pool relays from the ledger/database without depending on peer-governance policy types.

func NewPoolRelayProvider added in v0.55.0

func NewPoolRelayProvider(
	ledgerState *LedgerState,
	db *database.Database,
	eventBus *event.EventBus,
) (*PoolRelayProvider, error)

NewPoolRelayProvider creates a new ledger pool relay provider. Returns an error if ledgerState or db is nil.

func (*PoolRelayProvider) Close added in v0.69.0

func (p *PoolRelayProvider) Close()

Close unsubscribes the cache-invalidation handler registered in NewPoolRelayProvider. Safe to call on a provider constructed with a nil eventBus (no-op) and safe to call more than once.

func (*PoolRelayProvider) CurrentSlot added in v0.55.0

func (p *PoolRelayProvider) CurrentSlot() uint64

CurrentSlot returns the current chain tip slot number.

func (*PoolRelayProvider) GetPoolRelays added in v0.55.0

func (p *PoolRelayProvider) GetPoolRelays() (
	[]PoolRelay,
	error,
)

GetPoolRelays returns all active pool relays from the ledger.

func (*PoolRelayProvider) InvalidateCache added in v0.55.0

func (p *PoolRelayProvider) InvalidateCache()

InvalidateCache clears the cached pool relays, forcing the next GetPoolRelays call to fetch fresh data from the database.

type PoolStakeDistribution added in v0.70.0

type PoolStakeDistribution struct {
	// Tip is the chain tip read inside the same transaction as the stake rows.
	// It is what the distribution was evaluated against, so a caller reporting
	// a "the state as of" point must use this rather than sampling the tip
	// again afterwards: between the two reads the chain can advance, and across
	// an epoch boundary the later tip names an epoch whose snapshot is not the
	// one these rows came from.
	Tip ochainsync.Tip
	// SnapshotEpoch names the mark snapshot the distribution was read from,
	// which is the snapshot this node elects leaders from rather than live
	// stake.
	SnapshotEpoch uint64
	// TotalActiveStake is the whole snapshot's total, clamped to a minimum of
	// one. The clamp is inherited from totalActiveStake, where it exists
	// because cardano clients decode this as a NonZero value; see its doc
	// comment. It is the denominator every StakeFraction is taken over.
	TotalActiveStake uint64
	// TotalCirculatingSupply is genesis MaxLovelaceSupply minus the live
	// reserves pot, clamped the same way as TotalActiveStake. It is a
	// different total from TotalActiveStake -- see totalCirculatingSupply's
	// doc comment (blinklabs-io/dingo#3824) for why GetStakeDistribution, and
	// only GetStakeDistribution, needs this one instead.
	TotalCirculatingSupply uint64
	// Pools is ordered by PoolKeyHash. Callers that place this in a repeated
	// protobuf field or any other ordered encoding depend on that: without it
	// the order is Go map iteration order, so two identical requests against
	// an unchanged snapshot would differ.
	Pools []PoolStakeShare
}

PoolStakeDistribution is the stake distribution across block-producing pools as of SnapshotEpoch.

type PoolStakeShare added in v0.70.0

type PoolStakeShare struct {
	PoolKeyHash lcommon.PoolKeyHash
	// Stake is this pool's stake in the snapshot, in lovelace.
	Stake uint64
	// StakeFraction is Stake over PoolStakeDistribution.TotalActiveStake. It
	// is a share of the whole snapshot even when a filter was applied, so a
	// filtered distribution's fractions sum to less than one.
	StakeFraction *cbor.Rat
	// VrfKeyHash is the key block validation will hold this pool to.
	VrfKeyHash ledger.Blake2b256
}

PoolStakeShare is one pool's entry in the active stake distribution.

type PoolStateRestoredEvent added in v0.22.0

type PoolStateRestoredEvent struct {
	Slot uint64 // The slot to which pool state was restored
}

PoolStateRestoredEvent is emitted after pool state is restored during a rollback. Subscribers (like peer providers) can use this to invalidate cached pool data.

type ProtocolVersion added in v0.22.0

type ProtocolVersion struct {
	Major uint
	Minor uint
}

ProtocolVersion represents the major and minor protocol version numbers used in Cardano protocol parameters.

func GetProtocolVersion added in v0.22.0

func GetProtocolVersion(
	pparams lcommon.ProtocolParameters,
) (ProtocolVersion, error)

GetProtocolVersion extracts the protocol version from protocol parameters. This works across all eras by type- switching on the concrete pparams type. Returns an error if the pparams type is not recognized or nil.

type RecordBlockfetchLatencyFunc added in v0.38.0

type RecordBlockfetchLatencyFunc func(ouroboros.ConnectionId, time.Duration)

RecordBlockfetchLatencyFunc records a first-block latency sample for the given connection after a successful RequestRange response.

type ScheduledTask added in v0.14.0

type ScheduledTask struct {
	// contains filtered or unexported fields
}

type Scheduler added in v0.14.0

type Scheduler struct {
	// contains filtered or unexported fields
}

func NewScheduler added in v0.14.0

func NewScheduler(interval time.Duration) *Scheduler

func NewSchedulerWithConfig added in v0.19.0

func NewSchedulerWithConfig(
	interval time.Duration,
	config SchedulerConfig,
) *Scheduler

func (*Scheduler) ChangeInterval added in v0.14.0

func (st *Scheduler) ChangeInterval(newInterval time.Duration) error

ChangeInterval updates the tick interval of the Scheduler at runtime. It returns an error if newInterval is not positive.

func (*Scheduler) Register added in v0.14.0

func (st *Scheduler) Register(
	interval int,
	taskFunc func(),
	runFailFunc func(),
)

Adds a new task to be scheduler

func (*Scheduler) Start added in v0.14.0

func (st *Scheduler) Start()

Start the timer (run goroutine once)

func (*Scheduler) Stop added in v0.14.0

func (st *Scheduler) Stop()

Stop terminates the scheduler. Start and Stop share lifecycleMutex so a shutdown racing startup either prevents startup or tears down everything Start created before returning.

type SchedulerConfig added in v0.19.0

type SchedulerConfig struct {
	WorkerPoolSize int
	TaskQueueSize  int
}

func DefaultSchedulerConfig added in v0.19.0

func DefaultSchedulerConfig() SchedulerConfig

type SlotBattleRecorder added in v0.22.0

type SlotBattleRecorder interface {
	// RecordSlotBattle increments the slot battle counter.
	RecordSlotBattle()
}

SlotBattleRecorder records slot battle events for metrics.

type SlotClock added in v0.22.0

type SlotClock struct {
	// contains filtered or unexported fields
}

SlotClock provides slot-boundary-aware timing for the Cardano node. It ticks at each slot boundary and notifies subscribers, enabling time-based operations like epoch transitions and block production that don't depend on incoming blocks.

The SlotClock provides two categories of functionality:

  1. Query methods (CurrentSlot, CurrentEpoch, GetEpochForSlot, etc.) that work in all modes (catch up, load, synced) and can be called anytime.
  2. Tick notifications that fire at real-time slot boundaries, useful for leader election and proactive epoch detection when synced to tip.

func NewSlotClock added in v0.22.0

func NewSlotClock(
	provider SlotTimeProvider,
	config SlotClockConfig,
) *SlotClock

NewSlotClock creates a new SlotClock with the given provider and configuration

func (*SlotClock) CurrentEpoch added in v0.22.0

func (sc *SlotClock) CurrentEpoch() (EpochInfo, error)

CurrentEpoch returns the current epoch based on wall-clock time. This works regardless of sync state and can be called during catch up or load.

func (*SlotClock) CurrentSlot added in v0.22.0

func (sc *SlotClock) CurrentSlot() (uint64, error)

CurrentSlot returns the current slot number based on wall-clock time. This works regardless of sync state and can be called during catch up or load.

func (*SlotClock) GetEpochForSlot added in v0.22.0

func (sc *SlotClock) GetEpochForSlot(slot uint64) (EpochInfo, error)

GetEpochForSlot returns epoch information for the given slot. This works regardless of sync state and can be called during catch up or load.

func (*SlotClock) IsEpochBoundary added in v0.22.0

func (sc *SlotClock) IsEpochBoundary(slot uint64) (bool, error)

IsEpochBoundary returns true if the given slot is the first slot of an epoch.

func (*SlotClock) LastEmittedEpoch added in v0.22.0

func (sc *SlotClock) LastEmittedEpoch() uint64

LastEmittedEpoch returns the last epoch for which an event was emitted.

func (*SlotClock) MarkEpochEmitted added in v0.22.0

func (sc *SlotClock) MarkEpochEmitted(epoch uint64) bool

MarkEpochEmitted records that an epoch transition event was emitted for the given epoch. This is used to coordinate between slot-based and block-based epoch detection to avoid duplicate events. Returns true if this is a new epoch (not previously emitted), false if duplicate.

func (*SlotClock) NextSlotTime added in v0.22.0

func (sc *SlotClock) NextSlotTime() (time.Time, error)

NextSlotTime returns the time when the next slot will start

func (*SlotClock) SetLastEmittedEpoch added in v0.22.0

func (sc *SlotClock) SetLastEmittedEpoch(epoch uint64)

SetLastEmittedEpoch sets the last emitted epoch. Used during startup to initialize the tracker based on stored state.

func (*SlotClock) SlotToTime added in v0.22.0

func (sc *SlotClock) SlotToTime(slot uint64) (time.Time, error)

SlotToTime returns the time when the given slot starts. This works regardless of sync state and can be called during catch up or load.

func (*SlotClock) Start added in v0.22.0

func (sc *SlotClock) Start(ctx context.Context)

Start begins the slot clock ticking loop. The clock will emit SlotTick notifications at each slot boundary. Returns immediately; the tick loop runs in a goroutine.

func (*SlotClock) Stop added in v0.22.0

func (sc *SlotClock) Stop()

Stop halts the slot clock and waits for the tick loop to exit. All subscriber channels will be closed, causing any goroutines blocked on receiving from them to exit cleanly.

func (*SlotClock) Subscribe added in v0.22.0

func (sc *SlotClock) Subscribe() <-chan SlotTick

Subscribe returns a channel that will receive SlotTick notifications. The channel is buffered to prevent blocking the clock loop. Call Unsubscribe to stop receiving notifications and close the channel.

func (*SlotClock) TimeUntilNextEpoch added in v0.22.0

func (sc *SlotClock) TimeUntilNextEpoch() (time.Duration, error)

TimeUntilNextEpoch returns the duration until the next epoch boundary. This works regardless of sync state and can be called during catch up or load.

func (*SlotClock) TimeUntilSlot added in v0.22.0

func (sc *SlotClock) TimeUntilSlot(slot uint64) (time.Duration, error)

TimeUntilSlot returns the duration until the given slot starts. Returns negative duration if the slot is in the past.

func (*SlotClock) Unsubscribe added in v0.22.0

func (sc *SlotClock) Unsubscribe(ch <-chan SlotTick)

Unsubscribe removes a subscriber channel from the notification list. The channel will be closed after this call.

type SlotClockConfig added in v0.22.0

type SlotClockConfig struct {
	// Logger for slot clock events
	Logger *slog.Logger
	// ClockTolerance is the maximum drift allowed when waking at slot boundaries.
	// If we wake up more than this much after the slot boundary, we log a warning.
	// Set high enough to ride out normal Go scheduler / GC pause jitter on a busy
	// node — only sustained or large drifts indicate a real timing problem.
	// Default: 500ms.
	ClockTolerance time.Duration
}

SlotClockConfig holds configuration for the SlotClock

func DefaultSlotClockConfig added in v0.22.0

func DefaultSlotClockConfig() SlotClockConfig

DefaultSlotClockConfig returns the default configuration

type SlotTick added in v0.22.0

type SlotTick struct {
	// Slot is the current slot number
	Slot uint64
	// SlotStart is the time when this slot started
	SlotStart time.Time
	// Epoch is the current epoch number
	Epoch uint64
	// EpochSlot is the slot number within the current epoch (0-indexed)
	EpochSlot uint64
	// IsEpochStart indicates whether this is the first slot of a new epoch
	IsEpochStart bool
	// SlotsUntilEpoch is the number of slots until the next epoch boundary
	SlotsUntilEpoch uint64
}

SlotTick represents a notification that a slot boundary has been reached

type SlotTimeConverter added in v0.69.0

type SlotTimeConverter struct {
	// contains filtered or unexported fields
}

SlotTimeConverter converts between Cardano slots and wall-clock time.

Era-boundary math is delegated to a hardfork.Summary obtained from the injected HardForkSummary accessor; this type layers the operational near-now fallbacks on top (see withinOperationalWindow) so the slot clock can keep resolving the next slot boundary while the applied ledger is behind the wall clock (from-genesis sync, `dingo load`, restart after downtime).

A SlotTimeConverter holds no lock of its own: era history and genesis are read fresh from the injected accessors on every call, so it is safe for concurrent use as long as those accessors are.

func NewSlotTimeConverter added in v0.69.0

func NewSlotTimeConverter(deps SlotTimeConverterDeps) *SlotTimeConverter

NewSlotTimeConverter creates a SlotTimeConverter with the given dependencies.

func (*SlotTimeConverter) EndorserBlockWaitDuration added in v0.69.0

func (c *SlotTimeConverter) EndorserBlockWaitDuration(
	waitSlots uint64,
) time.Duration

EndorserBlockWaitDuration returns the wall-clock window corresponding to waitSlots slots at the Shelley-era slot length, or 0 when waitSlots is 0 or the slot length is unknown.

func (*SlotTimeConverter) EpochInfo added in v0.69.0

func (c *SlotTimeConverter) EpochInfo(epoch uint64) (models.Epoch, error)

EpochInfo returns boundary information for the given epoch.

Epochs within the known epoch cache resolve to cached-era parameters; epochs past the cache are projected using the current era's parameters only through the configured safe-zone horizon. Returns an error for an empty cache or for epochs outside that range.

func (*SlotTimeConverter) SlotToEpoch added in v0.69.0

func (c *SlotTimeConverter) SlotToEpoch(slot uint64) (models.Epoch, error)

SlotToEpoch returns the epoch containing the given slot.

Slots within the known epoch cache resolve to the cached epoch's parameters; slots past the cache are projected using the current era's parameters only through the configured safe-zone horizon. Returns an error for an empty cache or for slots outside that range.

func (*SlotTimeConverter) SlotToTime added in v0.69.0

func (c *SlotTimeConverter) SlotToTime(slot uint64) (time.Time, error)

SlotToTime returns the wall-clock start time of the given slot.

Slot 0 always maps to Shelley genesis SystemStart, regardless of whether the epoch cache is populated. Other slots are resolved via the hardfork.Summary built from the current epoch cache. The current era can be projected only through its configured safe-zone horizon.

func (*SlotTimeConverter) SlotToTimeWithHorizonFrom added in v0.70.7

func (c *SlotTimeConverter) SlotToTimeWithHorizonFrom(
	horizonAnchorSlot uint64,
	slot uint64,
) (time.Time, error)

SlotToTimeWithHorizonFrom converts a slot with the forecast horizon measured from horizonAnchorSlot rather than from the published tip, and keeps the horizon: a slot past the anchored bound still returns hardfork.ErrPastHorizon.

Transaction validation needs this. Building a Plutus script context converts the transaction's validity interval to POSIX time, and cardano-ledger fails the transaction when that translation is refused (TimeTranslationPastHorizon, eras/alonzo/impl Cardano.Ledger.Alonzo.Plutus.TxInfo), so the bound itself is consensus-relevant and must stay. What diverged was the horizon's input: the published tip advances only when a whole block batch commits, while the reference measures the safe zone from the applied block's immediate predecessor. applySafeZone snaps up to an epoch boundary, so a tip trailing by a single block can cost a full epoch of horizon and reject a canonical block (issue #3844).

The near-now extrapolation SlotToTime applies is deliberately absent: it exists so the operational slot clock can tick while the ledger is behind the wall clock, and transaction validation must answer from era history alone.

func (*SlotTimeConverter) TimeToSlot added in v0.69.0

func (c *SlotTimeConverter) TimeToSlot(t time.Time) (uint64, error)

TimeToSlot returns the slot containing the given wall-clock time.

Returns ErrBeforeGenesis when t is before SystemStart. Near-now calls used by the operational slot clock retain current-era extrapolation when the ledger is empty or behind the HFC forecast horizon; arbitrary time queries remain bounded.

type SlotTimeConverterDeps added in v0.69.0

type SlotTimeConverterDeps struct {
	// HardForkSummary returns the current hardfork.Summary describing era
	// history, or an error when it cannot be built (e.g. no epochs known
	// yet). The current era's forecast horizon is measured from
	// max(the published tip slot, horizonAnchorSlot); 0 accepts the
	// published tip.
	HardForkSummary func(horizonAnchorSlot uint64) (*hardfork.Summary, error)
	// ShelleyGenesis returns the Shelley genesis config, or nil if it has
	// not been loaded.
	ShelleyGenesis func() *shelley.ShelleyGenesis
	// EpochCache returns the current epoch cache snapshot, most-recent-last.
	EpochCache func() []models.Epoch
}

SlotTimeConverterDeps supplies the accessors a SlotTimeConverter needs to convert between slots and wall-clock time. LedgerState remains the source of truth for era history (the consensus snapshot) and genesis config; the converter depends on them only through this narrow set of read-only callbacks, so it never reaches back into LedgerState's locking or working state directly.

type SlotTimeProvider added in v0.22.0

type SlotTimeProvider interface {
	SlotToTime(slot uint64) (time.Time, error)
	TimeToSlot(t time.Time) (uint64, error)
	SlotToEpoch(slot uint64) (EpochInfo, error)
}

SlotTimeProvider defines the interface for slot/time conversion This allows testing with mock time

type StakeDistribution added in v0.22.0

type StakeDistribution struct {
	Epoch      uint64            // Epoch this snapshot is for
	PoolStakes map[string]uint64 // poolKeyHash (hex) -> total stake
	TotalStake uint64            // Sum of all pool stakes
}

StakeDistribution represents the stake distribution at an epoch boundary. Used for leader election in Ouroboros Praos.

type TransactionEvent added in v0.22.0

type TransactionEvent struct {
	Transaction ledger.Transaction
	Point       ocommon.Point
	BlockNumber uint64
	TxIndex     uint32
	Rollback    bool
}

TransactionEvent is emitted after a transaction Apply commits durably, or before an applied transaction is rolled back. Check the Rollback field to determine direction.

type TransactionRecord added in v0.18.0

type TransactionRecord struct {
	Tx    lcommon.Transaction
	Index int
}

Directories

Path Synopsis
Package forging contains types and utilities for block production.
Package forging contains types and utilities for block production.
Package hardfork provides the HardFork Combinator primitives used by the ledger to reason about multi-era chain time, epoch, and slot conversions.
Package hardfork provides the HardFork Combinator primitives used by the ledger to reason about multi-era chain time, epoch, and slot conversions.
Package leader provides Ouroboros Praos leader election functionality for block production.
Package leader provides Ouroboros Praos leader election functionality for block production.
Package leios implements the CIP-0164 stake-truncated voting committee, stake-quorum vote tallying, and endorser-block certificate construction and validation.
Package leios implements the CIP-0164 stake-truncated voting committee, stake-quorum vote tallying, and endorser-block certificate construction and validation.
Package rewards implements the Shelley stake-pool reward calculation.
Package rewards implements the Shelley stake-pool reward calculation.
Package snapshot provides stake snapshot management for Ouroboros Praos leader election.
Package snapshot provides stake snapshot management for Ouroboros Praos leader election.

Jump to

Keyboard shortcuts

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