forging

package
v0.27.2 Latest Latest
Warning

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

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

Documentation

Overview

Package forging contains types and utilities for block production.

Block Propagation

Block propagation to peers is handled automatically by the chain package. When a forged block is added via chain.AddBlock(), the method closes the chain's waitingChan (see chain/chain.go lines 174-180), which signals any blocking ChainIterators. The ouroboros chainsync server (see ouroboros/chainsync.go chainsyncServerRequestNext) waits on these iterators via ChainIterator.Next(true), which blocks on waitingChan when at chain tip. When the channel is closed, iterators wake up and deliver the new block to connected peers via RollForward messages.

This means there is no need for explicit propagation logic when forging blocks - adding the block to the chain automatically triggers delivery to all subscribed chainsync clients.

Package forging provides block production functionality for Cardano SPOs.

Index

Constants

View Source
const SlotBattleEventType = event.EventType("forging.slot_battle")

SlotBattleEventType is the event type for slot battles (competing blocks)

Variables

This section is empty.

Functions

This section is empty.

Types

type BlockBroadcaster

type BlockBroadcaster interface {
	// AddBlock adds a block to the local chain and propagates to peers.
	AddBlock(block ledger.Block, cbor []byte) error
}

BlockBroadcaster submits built blocks to the chain.

type BlockBuilder

type BlockBuilder interface {
	// BuildBlock creates a new block for the given slot.
	// Returns the block and its CBOR encoding.
	BuildBlock(slot uint64, kesPeriod uint64) (ledger.Block, []byte, error)
}

BlockBuilder constructs blocks from mempool transactions.

type BlockBuilderConfig

type BlockBuilderConfig struct {
	Logger          *slog.Logger
	Mempool         MempoolProvider
	PParamsProvider ProtocolParamsProvider
	ChainTip        ChainTipProvider
	EpochNonce      EpochNonceProvider
	Credentials     *PoolCredentials
	// TxValidator optionally re-validates each transaction against
	// the current ledger state before including it in a block.
	// When nil, ledger-level re-validation is skipped (but
	// intra-block double-spend detection still applies).
	TxValidator TxValidator
}

BlockBuilderConfig holds configuration for the DefaultBlockBuilder.

type BlockForger

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

BlockForger coordinates block production for a stake pool.

func NewBlockForger

func NewBlockForger(cfg ForgerConfig) (*BlockForger, error)

NewBlockForger creates a new block forger.

func (*BlockForger) IsRunning

func (f *BlockForger) IsRunning() bool

IsRunning returns true if the forger is currently running.

func (*BlockForger) RecordSlotBattle

func (f *BlockForger) RecordSlotBattle()

RecordSlotBattle increments the slot battles counter. This is called from external components (e.g., LedgerState) when a slot battle is detected.

func (*BlockForger) SignBlockHeader

func (f *BlockForger) SignBlockHeader(
	kesPeriod uint64,
	headerBytes []byte,
) ([]byte, error)

SignBlockHeader signs a block header with KES.

func (*BlockForger) SlotTracker

func (f *BlockForger) SlotTracker() *SlotTracker

SlotTracker returns the forger's slot tracker, which can be used by other components (e.g., chainsync) to detect slot battles.

func (*BlockForger) Start

func (f *BlockForger) Start(ctx context.Context) error

Start begins the block forging process. The provided context controls the forger's lifecycle.

func (*BlockForger) Stop

func (f *BlockForger) Stop()

Stop stops the block forging process. It blocks until the runLoop goroutine has exited.

func (*BlockForger) VRFProofForSlot

func (f *BlockForger) VRFProofForSlot(
	slot uint64,
	epochNonce []byte,
) ([]byte, []byte, error)

VRFProofForSlot generates a VRF proof for leader election at the given slot. Returns (proof, output, error).

type ChainTipProvider

type ChainTipProvider interface {
	Tip() ochainsync.Tip
}

ChainTipProvider provides access to the current chain tip.

type DefaultBlockBuilder

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

DefaultBlockBuilder implements BlockBuilder using LedgerState components.

func NewDefaultBlockBuilder

func NewDefaultBlockBuilder(cfg BlockBuilderConfig) (*DefaultBlockBuilder, error)

NewDefaultBlockBuilder creates a new DefaultBlockBuilder.

func (*DefaultBlockBuilder) BuildBlock

func (b *DefaultBlockBuilder) BuildBlock(
	slot uint64,
	kesPeriod uint64,
) (ledger.Block, []byte, error)

BuildBlock creates a new block for the given slot. Returns the block and its CBOR encoding.

type EpochNonceProvider

type EpochNonceProvider interface {
	// CurrentEpoch returns the current epoch number.
	CurrentEpoch() uint64
	// EpochNonce returns the nonce for the given epoch.
	EpochNonce(epoch uint64) []byte
}

EpochNonceProvider provides the epoch nonce for VRF proof generation.

type ForgedBlockRecord

type ForgedBlockRecord struct {
	BlockHash []byte
}

ForgedBlockRecord stores the hash of a block we forged for a given slot.

type ForgerConfig

type ForgerConfig struct {
	Mode         Mode
	Logger       *slog.Logger
	SlotDuration time.Duration

	// Production mode configuration
	Credentials      *PoolCredentials
	LeaderChecker    LeaderChecker
	BlockBuilder     BlockBuilder
	BlockBroadcaster BlockBroadcaster
	SlotClock        SlotClockProvider

	// ForgeSyncToleranceSlots controls how far the local chain can lag the
	// upstream tip before forging is skipped. Zero uses the default.
	ForgeSyncToleranceSlots uint64
	// ForgeStaleGapThresholdSlots controls when to log an error if the
	// chain tip is far ahead of the slot clock. Zero uses the default.
	ForgeStaleGapThresholdSlots uint64

	// Prometheus metrics registry (optional)
	PromRegistry prometheus.Registerer
}

ForgerConfig holds configuration for the block forger.

type LeaderChecker

type LeaderChecker interface {
	// ShouldProduceBlock returns true if this pool is the leader for the slot.
	ShouldProduceBlock(slot uint64) bool
	// NextLeaderSlot returns the next slot where this pool is leader.
	NextLeaderSlot(fromSlot uint64) (uint64, bool)
}

LeaderChecker determines if the pool should produce a block for a given slot.

type MempoolProvider

type MempoolProvider interface {
	Transactions() []MempoolTransaction
}

MempoolProvider provides access to mempool transactions.

type MempoolTransaction

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

MempoolTransaction represents a transaction in the mempool.

type Mode

type Mode int

Mode represents the forging mode.

const (
	// ModeDev is a simplified mode where the node produces all blocks on a
	// fixed interval without real VRF/KES. Used for single-node devnets.
	ModeDev Mode = iota

	// ModeProduction uses real VRF leader election and KES signing.
	// Requires loaded pool credentials.
	ModeProduction
)

type OpCert

type OpCert struct {
	KESVKey     []byte // KES verification key (32 bytes)
	IssueNumber uint64 // Certificate sequence number
	KESPeriod   uint64 // KES period when certificate was created
	Signature   []byte // Cold key signature (64 bytes)
	ColdVKey    []byte // Cold verification key (32 bytes)
}

OpCert represents an operational certificate that binds a KES key to a pool.

type PoolCredentials

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

PoolCredentials holds the cryptographic keys required for block production. All keys are loaded using Bursa from standard cardano-cli format files. Fields are unexported to enforce thread-safe access via the mutex.

func NewPoolCredentials

func NewPoolCredentials() *PoolCredentials

NewPoolCredentials creates an empty PoolCredentials instance.

func (*PoolCredentials) GetKESPeriod

func (pc *PoolCredentials) GetKESPeriod() uint64

GetKESPeriod returns the current KES period of the loaded key. Returns 0 if the KES key is not loaded.

func (*PoolCredentials) GetKESVKey

func (pc *PoolCredentials) GetKESVKey() []byte

GetKESVKey returns a copy of the KES verification key.

func (*PoolCredentials) GetOpCert

func (pc *PoolCredentials) GetOpCert() *OpCert

GetOpCert returns a copy of the operational certificate. Returns nil if no certificate is loaded.

func (*PoolCredentials) GetPoolID

func (pc *PoolCredentials) GetPoolID() lcommon.PoolId

GetPoolID returns the pool ID (Blake2b-224 of cold vkey).

func (*PoolCredentials) GetVRFSKey

func (pc *PoolCredentials) GetVRFSKey() []byte

GetVRFSKey returns a copy of the VRF secret key (seed).

func (*PoolCredentials) GetVRFVKey

func (pc *PoolCredentials) GetVRFVKey() []byte

GetVRFVKey returns a copy of the VRF verification key.

func (*PoolCredentials) IsLoaded

func (pc *PoolCredentials) IsLoaded() bool

IsLoaded returns true if all credentials have been loaded.

func (*PoolCredentials) KESSign

func (pc *PoolCredentials) KESSign(period uint64, message []byte) ([]byte, error)

KESSign signs a message with the KES key at the specified absolute period. The absolute period is converted to a relative period using the opcert start KES period before signing.

func (*PoolCredentials) LoadFromFiles

func (pc *PoolCredentials) LoadFromFiles(
	vrfSKeyPath string,
	kesSKeyPath string,
	opCertPath string,
) error

LoadFromFiles loads all pool credentials from the specified file paths. Uses Bursa to parse cardano-cli format key files.

func (*PoolCredentials) OpCertExpiryPeriod

func (pc *PoolCredentials) OpCertExpiryPeriod() uint64

OpCertExpiryPeriod returns the KES period at which the OpCert expires. For depth 6, max periods = 2^6 = 64, so expiry = startPeriod + 64.

func (*PoolCredentials) PeriodsRemaining

func (pc *PoolCredentials) PeriodsRemaining(currentPeriod uint64) uint64

PeriodsRemaining returns how many KES periods remain before expiry.

func (*PoolCredentials) UpdateKESPeriod

func (pc *PoolCredentials) UpdateKESPeriod(period uint64) error

UpdateKESPeriod updates the KES key to the specified absolute period. The absolute period is converted to a relative period using the opcert start KES period before evolving.

func (*PoolCredentials) VRFProve

func (pc *PoolCredentials) VRFProve(alpha []byte) ([]byte, []byte, error)

VRFProve generates a VRF proof for leader election. alpha should be MkInputVrf(slot, epochNonce).

func (*PoolCredentials) ValidateOpCert

func (pc *PoolCredentials) ValidateOpCert() error

ValidateOpCert validates that the operational certificate matches the KES key and that the cold key signature over the certificate body is valid.

type ProtocolParamsProvider

type ProtocolParamsProvider interface {
	GetCurrentPParams() lcommon.ProtocolParameters
}

ProtocolParamsProvider provides access to protocol parameters.

type SlotBattleEvent

type SlotBattleEvent struct {
	// Slot is the slot number where the battle occurred
	Slot uint64
	// LocalBlockHash is the hash of our locally forged block (if any)
	LocalBlockHash []byte
	// RemoteBlockHash is the hash of the competing block from peers
	RemoteBlockHash []byte
	// Won indicates whether our local block was selected for the chain
	Won bool
}

SlotBattleEvent is emitted when the node detects competing blocks for the same slot, either from receiving an external block while preparing to forge or when detecting a fork at the same slot height.

type SlotClockProvider

type SlotClockProvider interface {
	// CurrentSlot returns the current slot number based on wall-clock time.
	CurrentSlot() (uint64, error)
	// SlotsPerKESPeriod returns the number of slots in a KES period.
	SlotsPerKESPeriod() uint64
	// ChainTipSlot returns the slot number of the current chain tip.
	ChainTipSlot() uint64
	// NextSlotTime returns the wall-clock time when the next slot begins.
	NextSlotTime() (time.Time, error)
	// UpstreamTipSlot returns the latest known tip slot from upstream peers.
	// Returns 0 if no upstream tip is known.
	UpstreamTipSlot() uint64
}

SlotClockProvider provides current slot information from the slot clock.

type SlotTracker

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

SlotTracker is a thread-safe tracker for recently forged block slots and their hashes. It allows chainsync to detect slot battles when an incoming block from a peer occupies a slot for which the local node has already forged a block.

func NewSlotTracker

func NewSlotTracker() *SlotTracker

NewSlotTracker creates a new SlotTracker with the default capacity.

func NewSlotTrackerWithCapacity

func NewSlotTrackerWithCapacity(maxSlots int) *SlotTracker

NewSlotTrackerWithCapacity creates a new SlotTracker with the given maximum capacity.

func (*SlotTracker) Len

func (st *SlotTracker) Len() int

Len returns the number of tracked forged slots.

func (*SlotTracker) RecordForgedBlock

func (st *SlotTracker) RecordForgedBlock(slot uint64, blockHash []byte)

RecordForgedBlock records that the local node forged a block with the given hash at the given slot. If the tracker is at capacity, the oldest entry is evicted.

func (*SlotTracker) WasForgedByUs

func (st *SlotTracker) WasForgedByUs(
	slot uint64,
) (blockHash []byte, ok bool)

WasForgedByUs checks whether the local node forged a block for the given slot. If so, it returns the block hash and true. Otherwise it returns nil, false.

type TxValidator

type TxValidator interface {
	ValidateTx(tx ledger.Transaction) error
}

TxValidator re-validates a transaction against the current ledger state at block assembly time. This catches transactions whose inputs have been consumed since they entered the mempool, protocol parameter changes, or other state mutations that invalidate previously-accepted transactions.

Jump to

Keyboard shortcuts

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