228 lines
7.1 KiB
Go
228 lines
7.1 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// Config holds all configuration for the MPC system
|
|
type Config struct {
|
|
Server ServerConfig `mapstructure:"server"`
|
|
Database DatabaseConfig `mapstructure:"database"`
|
|
Redis RedisConfig `mapstructure:"redis"`
|
|
RabbitMQ RabbitMQConfig `mapstructure:"rabbitmq"`
|
|
Consul ConsulConfig `mapstructure:"consul"`
|
|
JWT JWTConfig `mapstructure:"jwt"`
|
|
MPC MPCConfig `mapstructure:"mpc"`
|
|
Logger LoggerConfig `mapstructure:"logger"`
|
|
}
|
|
|
|
// ServerConfig holds server-related configuration
|
|
type ServerConfig struct {
|
|
GRPCPort int `mapstructure:"grpc_port"`
|
|
HTTPPort int `mapstructure:"http_port"`
|
|
Environment string `mapstructure:"environment"`
|
|
Timeout time.Duration `mapstructure:"timeout"`
|
|
TLSEnabled bool `mapstructure:"tls_enabled"`
|
|
TLSCertFile string `mapstructure:"tls_cert_file"`
|
|
TLSKeyFile string `mapstructure:"tls_key_file"`
|
|
}
|
|
|
|
// DatabaseConfig holds database configuration
|
|
type DatabaseConfig struct {
|
|
Host string `mapstructure:"host"`
|
|
Port int `mapstructure:"port"`
|
|
User string `mapstructure:"user"`
|
|
Password string `mapstructure:"password"`
|
|
DBName string `mapstructure:"dbname"`
|
|
SSLMode string `mapstructure:"sslmode"`
|
|
MaxOpenConns int `mapstructure:"max_open_conns"`
|
|
MaxIdleConns int `mapstructure:"max_idle_conns"`
|
|
ConnMaxLife time.Duration `mapstructure:"conn_max_life"`
|
|
}
|
|
|
|
// DSN returns the database connection string
|
|
func (c *DatabaseConfig) DSN() string {
|
|
return fmt.Sprintf(
|
|
"host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
|
|
c.Host, c.Port, c.User, c.Password, c.DBName, c.SSLMode,
|
|
)
|
|
}
|
|
|
|
// RedisConfig holds Redis configuration
|
|
type RedisConfig struct {
|
|
Host string `mapstructure:"host"`
|
|
Port int `mapstructure:"port"`
|
|
Password string `mapstructure:"password"`
|
|
DB int `mapstructure:"db"`
|
|
}
|
|
|
|
// Addr returns the Redis address
|
|
func (c *RedisConfig) Addr() string {
|
|
return fmt.Sprintf("%s:%d", c.Host, c.Port)
|
|
}
|
|
|
|
// RabbitMQConfig holds RabbitMQ configuration
|
|
type RabbitMQConfig struct {
|
|
Host string `mapstructure:"host"`
|
|
Port int `mapstructure:"port"`
|
|
User string `mapstructure:"user"`
|
|
Password string `mapstructure:"password"`
|
|
VHost string `mapstructure:"vhost"`
|
|
}
|
|
|
|
// URL returns the RabbitMQ connection URL
|
|
func (c *RabbitMQConfig) URL() string {
|
|
return fmt.Sprintf(
|
|
"amqp://%s:%s@%s:%d/%s",
|
|
c.User, c.Password, c.Host, c.Port, c.VHost,
|
|
)
|
|
}
|
|
|
|
// ConsulConfig holds Consul configuration
|
|
type ConsulConfig struct {
|
|
Host string `mapstructure:"host"`
|
|
Port int `mapstructure:"port"`
|
|
ServiceID string `mapstructure:"service_id"`
|
|
Tags []string `mapstructure:"tags"`
|
|
}
|
|
|
|
// Addr returns the Consul address
|
|
func (c *ConsulConfig) Addr() string {
|
|
return fmt.Sprintf("%s:%d", c.Host, c.Port)
|
|
}
|
|
|
|
// JWTConfig holds JWT configuration
|
|
type JWTConfig struct {
|
|
SecretKey string `mapstructure:"secret_key"`
|
|
Issuer string `mapstructure:"issuer"`
|
|
TokenExpiry time.Duration `mapstructure:"token_expiry"`
|
|
RefreshExpiry time.Duration `mapstructure:"refresh_expiry"`
|
|
}
|
|
|
|
// MPCConfig holds MPC-specific configuration
|
|
type MPCConfig struct {
|
|
DefaultThresholdN int `mapstructure:"default_threshold_n"`
|
|
DefaultThresholdT int `mapstructure:"default_threshold_t"`
|
|
SessionTimeout time.Duration `mapstructure:"session_timeout"`
|
|
MessageTimeout time.Duration `mapstructure:"message_timeout"`
|
|
KeygenTimeout time.Duration `mapstructure:"keygen_timeout"`
|
|
SigningTimeout time.Duration `mapstructure:"signing_timeout"`
|
|
MaxParties int `mapstructure:"max_parties"`
|
|
}
|
|
|
|
// LoggerConfig holds logger configuration
|
|
type LoggerConfig struct {
|
|
Level string `mapstructure:"level"`
|
|
Encoding string `mapstructure:"encoding"`
|
|
OutputPath string `mapstructure:"output_path"`
|
|
}
|
|
|
|
// Load loads configuration from file and environment variables
|
|
func Load(configPath string) (*Config, error) {
|
|
v := viper.New()
|
|
|
|
// Set default values
|
|
setDefaults(v)
|
|
|
|
// Read config file
|
|
if configPath != "" {
|
|
v.SetConfigFile(configPath)
|
|
} else {
|
|
v.SetConfigName("config")
|
|
v.SetConfigType("yaml")
|
|
v.AddConfigPath(".")
|
|
v.AddConfigPath("./config")
|
|
v.AddConfigPath("/etc/mpc-system/")
|
|
}
|
|
|
|
// Read environment variables
|
|
v.SetEnvPrefix("MPC")
|
|
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
|
v.AutomaticEnv()
|
|
|
|
// Read config file (if exists)
|
|
if err := v.ReadInConfig(); err != nil {
|
|
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
|
|
return nil, fmt.Errorf("failed to read config file: %w", err)
|
|
}
|
|
// Config file not found is not an error, we'll use defaults + env vars
|
|
}
|
|
|
|
var config Config
|
|
if err := v.Unmarshal(&config); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
|
|
}
|
|
|
|
return &config, nil
|
|
}
|
|
|
|
// setDefaults sets default configuration values
|
|
func setDefaults(v *viper.Viper) {
|
|
// Server defaults
|
|
v.SetDefault("server.grpc_port", 50051)
|
|
v.SetDefault("server.http_port", 8080)
|
|
v.SetDefault("server.environment", "development")
|
|
v.SetDefault("server.timeout", "30s")
|
|
v.SetDefault("server.tls_enabled", false)
|
|
|
|
// Database defaults
|
|
v.SetDefault("database.host", "localhost")
|
|
v.SetDefault("database.port", 5432)
|
|
v.SetDefault("database.user", "mpc_user")
|
|
v.SetDefault("database.password", "")
|
|
v.SetDefault("database.dbname", "mpc_system")
|
|
v.SetDefault("database.sslmode", "disable")
|
|
v.SetDefault("database.max_open_conns", 25)
|
|
v.SetDefault("database.max_idle_conns", 5)
|
|
v.SetDefault("database.conn_max_life", "5m")
|
|
|
|
// Redis defaults
|
|
v.SetDefault("redis.host", "localhost")
|
|
v.SetDefault("redis.port", 6379)
|
|
v.SetDefault("redis.password", "")
|
|
v.SetDefault("redis.db", 0)
|
|
|
|
// RabbitMQ defaults
|
|
v.SetDefault("rabbitmq.host", "localhost")
|
|
v.SetDefault("rabbitmq.port", 5672)
|
|
v.SetDefault("rabbitmq.user", "guest")
|
|
v.SetDefault("rabbitmq.password", "guest")
|
|
v.SetDefault("rabbitmq.vhost", "/")
|
|
|
|
// Consul defaults
|
|
v.SetDefault("consul.host", "localhost")
|
|
v.SetDefault("consul.port", 8500)
|
|
|
|
// JWT defaults
|
|
v.SetDefault("jwt.issuer", "mpc-system")
|
|
v.SetDefault("jwt.token_expiry", "15m")
|
|
v.SetDefault("jwt.refresh_expiry", "24h")
|
|
|
|
// MPC defaults
|
|
v.SetDefault("mpc.default_threshold_n", 3)
|
|
v.SetDefault("mpc.default_threshold_t", 2)
|
|
v.SetDefault("mpc.session_timeout", "10m")
|
|
v.SetDefault("mpc.message_timeout", "30s")
|
|
v.SetDefault("mpc.keygen_timeout", "10m")
|
|
v.SetDefault("mpc.signing_timeout", "5m")
|
|
v.SetDefault("mpc.max_parties", 10)
|
|
|
|
// Logger defaults
|
|
v.SetDefault("logger.level", "info")
|
|
v.SetDefault("logger.encoding", "json")
|
|
v.SetDefault("logger.output_path", "stdout")
|
|
}
|
|
|
|
// MustLoad loads configuration and panics on error
|
|
func MustLoad(configPath string) *Config {
|
|
cfg, err := Load(configPath)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("failed to load config: %v", err))
|
|
}
|
|
return cfg
|
|
}
|