Files
consensus/runtime/runtime.go
T
zeekay 45f97a70ab fix: break import cycle by defining SharedMemory locally
Define Element, Requests, and SharedMemory types locally in
runtime package instead of importing from vm/chains/atomic.
This breaks the import cycle:
consensus → vm → consensus
2026-01-26 08:27:21 -08:00

321 lines
9.0 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
// Package runtime provides chain wiring and runtime dependencies for VMs.
// This package is part of the consensus module and provides the Runtime struct
// that VMs use for chain configuration, logging, validators, etc.
//
// Use stdlib context.Context for cancellation/deadlines.
// Use *Runtime for chain wiring (IDs, logging, validators, etc.)
package runtime
import (
"context"
"sync"
"time"
validators "github.com/luxfi/consensus/validator"
"github.com/luxfi/database"
"github.com/luxfi/ids"
"github.com/luxfi/metric"
"github.com/luxfi/warp"
)
// Element represents an atomic operation element.
// This mirrors vm/chains/atomic.Element to avoid import cycles.
type Element struct {
Key []byte `serialize:"true"`
Value []byte `serialize:"true"`
Traits [][]byte `serialize:"true"`
}
// Requests represents atomic operation requests.
// This mirrors vm/chains/atomic.Requests to avoid import cycles.
type Requests struct {
RemoveRequests [][]byte `serialize:"true"`
PutRequests []*Element `serialize:"true"`
}
// ValidatorState is an alias to validators.State for convenience
type ValidatorState = validators.State
// Runtime provides chain wiring and runtime dependencies for VMs.
// This is separate from stdlib context.Context which handles cancellation/deadlines.
//
// Use context.Context for:
// - Cancellation signals
// - Request deadlines
// - Request-scoped values (sparingly)
//
// Use *Runtime for:
// - Chain IDs, network IDs
// - Node identity (NodeID, PublicKey)
// - Logging, metrics
// - Database handles
// - Validator state
// - Upgrade configurations
type Runtime struct {
// NetworkID is the numeric network identifier (1=mainnet, 2=testnet)
NetworkID uint32 `json:"networkID"`
// ChainID identifies the specific chain within the network
ChainID ids.ID `json:"chainID"`
// NodeID identifies this node
NodeID ids.NodeID `json:"nodeID"`
// PublicKey is the node's BLS public key bytes
PublicKey []byte `json:"publicKey"`
// XChainID is the X-Chain identifier
XChainID ids.ID `json:"xChainID"`
// CChainID is the C-Chain identifier
CChainID ids.ID `json:"cChainID"`
// XAssetID is the primary asset ID (X-chain native, typically LUX)
XAssetID ids.ID `json:"xAssetID"`
// ChainDataDir is the directory for chain-specific data
ChainDataDir string `json:"chainDataDir"`
// StartTime is when the node started
StartTime time.Time `json:"startTime"`
// ValidatorState provides validator information (uses consensus/validators.State)
ValidatorState validators.State
// Keystore provides key management
Keystore Keystore
// Metrics provides metrics tracking
Metrics Metrics
// Log provides logging
Log Logger
// SharedMemory provides cross-chain atomic operations
SharedMemory SharedMemory
// BCLookup provides blockchain alias lookup
BCLookup BCLookup
// WarpSigner provides BLS signing for Warp messages
WarpSigner WarpSigner
// NetworkUpgrades contains upgrade activation times
NetworkUpgrades NetworkUpgrades
// Lock for thread-safe access to runtime fields
Lock sync.RWMutex
}
// BCLookup provides blockchain alias lookup
type BCLookup interface {
Lookup(alias string) (ids.ID, error)
PrimaryAlias(id ids.ID) (string, error)
Aliases(id ids.ID) ([]string, error)
}
// Keystore provides key management
type Keystore interface {
GetDatabase(username, password string) (interface{}, error)
NewAccount(username, password string) error
}
// Logger provides logging functionality
type Logger interface {
Debug(msg string, fields ...interface{})
Info(msg string, fields ...interface{})
Warn(msg string, fields ...interface{})
Error(msg string, fields ...interface{})
Fatal(msg string, fields ...interface{})
}
// Metrics provides metrics tracking.
// Matches api/metrics.MultiGatherer interface.
type Metrics interface {
metric.Gatherer
Register(name string, gatherer metric.Gatherer) error
}
// SharedMemory is the canonical interface for cross-chain atomic operations.
// This interface mirrors vm/chains/atomic.SharedMemory to avoid import cycles.
type SharedMemory interface {
// Get fetches values corresponding to keys that have been sent from peerChainID
Get(peerChainID ids.ID, keys [][]byte) (values [][]byte, err error)
// Indexed returns a paginated result of values with given traits from peerChainID
Indexed(
peerChainID ids.ID,
traits [][]byte,
startTrait,
startKey []byte,
limit int,
) (values [][]byte, lastTrait, lastKey []byte, err error)
// Apply atomically applies requests to chainID keys in the map with batches
Apply(requests map[ids.ID]*Requests, batches ...database.Batch) error
}
// WarpSigner provides BLS signing for Warp messages.
// Matches warp.Signer interface exactly.
type WarpSigner = warp.Signer
// NetworkUpgrades contains network upgrade activation times.
// Matches upgrade.Config methods exactly.
type NetworkUpgrades interface {
IsApricotPhase1Activated(timestamp time.Time) bool
IsApricotPhase2Activated(timestamp time.Time) bool
IsApricotPhase3Activated(timestamp time.Time) bool
IsApricotPhase4Activated(timestamp time.Time) bool
IsApricotPhase5Activated(timestamp time.Time) bool
IsApricotPhasePre6Activated(timestamp time.Time) bool
IsApricotPhase6Activated(timestamp time.Time) bool
IsApricotPhasePost6Activated(timestamp time.Time) bool
IsBanffActivated(timestamp time.Time) bool
IsCortinaActivated(timestamp time.Time) bool
IsDurangoActivated(timestamp time.Time) bool
IsEtnaActivated(timestamp time.Time) bool
IsFortunaActivated(timestamp time.Time) bool
IsGraniteActivated(timestamp time.Time) bool
}
// VMContext is an interface that VM contexts must implement
// This allows different context types (node, plugin, etc.) to be used interchangeably
type VMContext interface {
GetNetworkID() uint32
GetChainID() ids.ID
GetNodeID() ids.NodeID
GetPublicKey() []byte
GetXChainID() ids.ID
GetCChainID() ids.ID
GetAssetID() ids.ID
GetChainDataDir() string
GetLog() interface{}
GetSharedMemory() interface{}
GetMetrics() interface{}
GetValidatorState() interface{}
GetBCLookup() interface{}
GetWarpSigner() interface{}
GetNetworkUpgrades() interface{}
}
// runtimeKeyType is the context key type for storing Runtime
type runtimeKeyType struct{}
var runtimeKey = runtimeKeyType{}
// WithRuntime adds Runtime to a context.Context
func WithRuntime(ctx context.Context, rt *Runtime) context.Context {
return context.WithValue(ctx, runtimeKey, rt)
}
// FromContext extracts Runtime from a context.Context
func FromContext(ctx context.Context) *Runtime {
if rt, ok := ctx.Value(runtimeKey).(*Runtime); ok {
return rt
}
return nil
}
// GetChainID gets the chain ID from context
func GetChainID(ctx context.Context) ids.ID {
if rt := FromContext(ctx); rt != nil {
return rt.ChainID
}
return ids.Empty
}
// GetNetworkID gets the numeric network ID from context
func GetNetworkID(ctx context.Context) uint32 {
if rt := FromContext(ctx); rt != nil {
return rt.NetworkID
}
return 0
}
// GetNodeID gets the node ID from context
func GetNodeID(ctx context.Context) ids.NodeID {
if rt := FromContext(ctx); rt != nil {
return rt.NodeID
}
return ids.EmptyNodeID
}
// IsPrimaryNetwork checks if the network is the primary network
func IsPrimaryNetwork(ctx context.Context) bool {
if rt := FromContext(ctx); rt != nil {
return rt.NetworkID == 1
}
return false
}
// GetValidatorState gets the validator state from context
func GetValidatorState(ctx context.Context) validators.State {
if rt := FromContext(ctx); rt != nil {
return rt.ValidatorState
}
return nil
}
// GetWarpSigner gets the warp signer from context
func GetWarpSigner(ctx context.Context) WarpSigner {
if rt := FromContext(ctx); rt != nil {
return rt.WarpSigner
}
return nil
}
// IDs holds the IDs for runtime context
type IDs struct {
NetworkID uint32
ChainID ids.ID
NodeID ids.NodeID
PublicKey []byte
XAssetID ids.ID
ChainDataDir string `json:"chainDataDir"`
}
// WithIDs adds IDs to the context via Runtime
func WithIDs(ctx context.Context, id IDs) context.Context {
rt := FromContext(ctx)
if rt == nil {
rt = &Runtime{}
}
rt.NetworkID = id.NetworkID
rt.ChainID = id.ChainID
rt.NodeID = id.NodeID
rt.PublicKey = id.PublicKey
rt.XAssetID = id.XAssetID
rt.ChainDataDir = id.ChainDataDir
return WithRuntime(ctx, rt)
}
// WithValidatorState adds validator state to the context
func WithValidatorState(ctx context.Context, vs validators.State) context.Context {
rt := FromContext(ctx)
if rt == nil {
rt = &Runtime{}
}
rt.ValidatorState = vs
return WithRuntime(ctx, rt)
}
// GetTimestamp returns the current timestamp
func GetTimestamp() int64 {
return time.Now().Unix()
}
// AsBCLookup returns the BCLookup interface for blockchain alias lookup.
// This method is used by VMs (particularly coreth) to resolve chain aliases.
func (r *Runtime) AsBCLookup() BCLookup {
if r == nil {
return nil
}
return r.BCLookup
}
// GetValidatorOutput is re-exported from validator package for convenience
type GetValidatorOutput = validators.GetValidatorOutput