mirror of
https://github.com/luxfi/consensus.git
synced 2026-09-24 00:26:58 +00:00
298 lines
8.1 KiB
Go
298 lines
8.1 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"`
|
|
|
|
// UTXOAssetID is the primary asset ID (X-chain native, typically LUX)
|
|
UTXOAssetID ids.ID `json:"utxoAssetID"`
|
|
|
|
// 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
|
|
|
|
// 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
|
|
|
|
// 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{}
|
|
}
|
|
|
|
// 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
|
|
UTXOAssetID 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.UTXOAssetID = id.UTXOAssetID
|
|
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
|