mirror of
https://github.com/luxfi/node.git
synced 2026-07-27 03:39:39 +00:00
125 lines
3.5 KiB
Go
125 lines
3.5 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package chains
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
|
|
"github.com/luxfi/database"
|
|
"github.com/luxfi/database/prefixdb"
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/log"
|
|
)
|
|
|
|
// ChainDBManager manages chain database access using a single global ZapDB.
|
|
// All chains share one ZapDB instance with prefix-based isolation:
|
|
// 1. Single database - easier to manage, backup, and query across chains
|
|
// 2. Prefix isolation - each chain's data is prefixed by its chainID
|
|
// 3. G-Chain compatible - dgraph can index the entire database for GraphQL queries
|
|
type ChainDBManager struct {
|
|
mu sync.RWMutex
|
|
|
|
// Global shared database (ZapDB)
|
|
db database.Database
|
|
|
|
// Cached prefixed databases per chain
|
|
chainDBs map[ids.ID]database.Database
|
|
|
|
log log.Logger
|
|
}
|
|
|
|
// ChainDBManagerConfig holds configuration for the chain database manager
|
|
type ChainDBManagerConfig struct {
|
|
// DB is the global shared database (ZapDB)
|
|
DB database.Database
|
|
|
|
Log log.Logger
|
|
}
|
|
|
|
// NewChainDBManager creates a new chain database manager using a single global ZapDB
|
|
func NewChainDBManager(config ChainDBManagerConfig) *ChainDBManager {
|
|
return &ChainDBManager{
|
|
db: config.DB,
|
|
chainDBs: make(map[ids.ID]database.Database),
|
|
log: config.Log,
|
|
}
|
|
}
|
|
|
|
// GetDatabase returns a prefixed database for the given chain.
|
|
// Uses prefix-based isolation on the single global ZapDB.
|
|
func (m *ChainDBManager) GetDatabase(chainID ids.ID, chainAlias string) (database.Database, error) {
|
|
if m.db == nil {
|
|
return nil, fmt.Errorf("global database not initialized")
|
|
}
|
|
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
// Check cache first
|
|
if db, exists := m.chainDBs[chainID]; exists {
|
|
return db, nil
|
|
}
|
|
|
|
// Create prefixed database for this chain
|
|
chainDB := prefixdb.New(chainID[:], m.db)
|
|
m.chainDBs[chainID] = chainDB
|
|
|
|
if !m.log.IsZero() {
|
|
m.log.Info("Created prefixed database for chain",
|
|
log.Stringer("chainID", chainID),
|
|
log.String("alias", chainAlias),
|
|
)
|
|
}
|
|
|
|
return chainDB, nil
|
|
}
|
|
|
|
// GetVMDatabase returns a VM-prefixed database for the given chain.
|
|
// Adds a "vm" prefix within the chain's prefix for VM-specific data.
|
|
func (m *ChainDBManager) GetVMDatabase(chainID ids.ID, chainAlias string) (database.Database, error) {
|
|
chainDB, err := m.GetDatabase(chainID, chainAlias)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Add VM prefix to isolate VM data from other chain data
|
|
return prefixdb.New(VMDBPrefix, chainDB), nil
|
|
}
|
|
|
|
// GetGlobalDB returns the underlying global database.
|
|
// This is useful for G-Chain (dgraph-powered GraphQL VM) to query across all chains.
|
|
func (m *ChainDBManager) GetGlobalDB() database.Database {
|
|
return m.db
|
|
}
|
|
|
|
// Close is a no-op since the global database lifecycle is managed elsewhere.
|
|
// Chain-specific prefixed databases don't need to be closed separately.
|
|
func (m *ChainDBManager) Close() error {
|
|
// Clear cache
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
m.chainDBs = make(map[ids.ID]database.Database)
|
|
return nil
|
|
}
|
|
|
|
// GetAllChainIDs returns all chain IDs that have databases allocated.
|
|
// Useful for G-Chain to enumerate chains for indexing.
|
|
func (m *ChainDBManager) GetAllChainIDs() []ids.ID {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
|
|
result := make([]ids.ID, 0, len(m.chainDBs))
|
|
for id := range m.chainDBs {
|
|
result = append(result, id)
|
|
}
|
|
return result
|
|
}
|
|
|
|
// GetDatabasePrefix returns the prefix used for a chain's data.
|
|
// This is the chainID bytes, which can be used by G-Chain to iterate chain data.
|
|
func (m *ChainDBManager) GetDatabasePrefix(chainID ids.ID) []byte {
|
|
return chainID[:]
|
|
}
|