Add pow config
This commit is contained in:
parent
c5dcc2acce
commit
859bd989be
147
internal/pow/challenge/config.go
Normal file
147
internal/pow/challenge/config.go
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
package challenge
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Config holds configuration for the PoW system
|
||||
type Config struct {
|
||||
DefaultDifficulty int // Default difficulty in bits (e.g., 4)
|
||||
MaxDifficulty int // Maximum allowed difficulty (e.g., 10)
|
||||
MinDifficulty int // Minimum allowed difficulty (e.g., 3)
|
||||
ChallengeTTL time.Duration // Time-to-live for challenges (e.g., 5 minutes)
|
||||
HMACSecret []byte // Secret key for HMAC signing
|
||||
Resource string // Resource identifier (e.g., "quotes")
|
||||
RandomBytes int // Number of random bytes in challenge (e.g., 6)
|
||||
LoadAdjustmentBits int // Extra difficulty bits when server under load
|
||||
FailurePenaltyBits int // Extra difficulty bits per failure group
|
||||
MaxFailurePenaltyBits int // Maximum failure penalty bits
|
||||
}
|
||||
|
||||
// configOption represents a functional option for Config
|
||||
type configOption func(*Config)
|
||||
|
||||
// WithDefaultDifficulty sets the default difficulty
|
||||
func WithDefaultDifficulty(difficulty int) configOption {
|
||||
return func(c *Config) {
|
||||
c.DefaultDifficulty = difficulty
|
||||
}
|
||||
}
|
||||
|
||||
// WithMaxDifficulty sets the maximum difficulty
|
||||
func WithMaxDifficulty(difficulty int) configOption {
|
||||
return func(c *Config) {
|
||||
c.MaxDifficulty = difficulty
|
||||
}
|
||||
}
|
||||
|
||||
// WithMinDifficulty sets the minimum difficulty
|
||||
func WithMinDifficulty(difficulty int) configOption {
|
||||
return func(c *Config) {
|
||||
c.MinDifficulty = difficulty
|
||||
}
|
||||
}
|
||||
|
||||
// WithChallengeTTL sets the challenge time-to-live
|
||||
func WithChallengeTTL(ttl time.Duration) configOption {
|
||||
return func(c *Config) {
|
||||
c.ChallengeTTL = ttl
|
||||
}
|
||||
}
|
||||
|
||||
// WithHMACSecret sets the HMAC secret
|
||||
func WithHMACSecret(secret []byte) configOption {
|
||||
return func(c *Config) {
|
||||
c.HMACSecret = secret
|
||||
}
|
||||
}
|
||||
|
||||
// WithResource sets the resource identifier
|
||||
func WithResource(resource string) configOption {
|
||||
return func(c *Config) {
|
||||
c.Resource = resource
|
||||
}
|
||||
}
|
||||
|
||||
// WithRandomBytes sets the number of random bytes
|
||||
func WithRandomBytes(bytes int) configOption {
|
||||
return func(c *Config) {
|
||||
c.RandomBytes = bytes
|
||||
}
|
||||
}
|
||||
|
||||
// WithLoadAdjustmentBits sets the load adjustment bits
|
||||
func WithLoadAdjustmentBits(bits int) configOption {
|
||||
return func(c *Config) {
|
||||
c.LoadAdjustmentBits = bits
|
||||
}
|
||||
}
|
||||
|
||||
// WithFailurePenaltyBits sets the failure penalty bits
|
||||
func WithFailurePenaltyBits(bits int) configOption {
|
||||
return func(c *Config) {
|
||||
c.FailurePenaltyBits = bits
|
||||
}
|
||||
}
|
||||
|
||||
// WithMaxFailurePenaltyBits sets the maximum failure penalty bits
|
||||
func WithMaxFailurePenaltyBits(bits int) configOption {
|
||||
return func(c *Config) {
|
||||
c.MaxFailurePenaltyBits = bits
|
||||
}
|
||||
}
|
||||
|
||||
// NewConfig creates and validates a new PoW configuration with defaults
|
||||
func NewConfig(opts ...configOption) (*Config, error) {
|
||||
// Generate default HMAC secret
|
||||
secret := make([]byte, 32)
|
||||
rand.Read(secret)
|
||||
|
||||
// Create config with defaults
|
||||
config := &Config{
|
||||
DefaultDifficulty: 4,
|
||||
MaxDifficulty: 10,
|
||||
MinDifficulty: 3,
|
||||
ChallengeTTL: 5 * time.Minute,
|
||||
HMACSecret: secret,
|
||||
Resource: "quotes",
|
||||
RandomBytes: 6,
|
||||
LoadAdjustmentBits: 1,
|
||||
FailurePenaltyBits: 2,
|
||||
MaxFailurePenaltyBits: 6,
|
||||
}
|
||||
|
||||
// Apply options
|
||||
for _, opt := range opts {
|
||||
opt(config)
|
||||
}
|
||||
|
||||
// Validate configuration
|
||||
if config.RandomBytes <= 0 || config.RandomBytes > 32 {
|
||||
return nil, fmt.Errorf("%w: random bytes must be between 1-32, got %d", ErrInvalidConfig, config.RandomBytes)
|
||||
}
|
||||
|
||||
if config.MinDifficulty < 1 {
|
||||
return nil, fmt.Errorf("%w: minimum difficulty must be >= 1, got %d", ErrInvalidConfig, config.MinDifficulty)
|
||||
}
|
||||
|
||||
if config.MaxDifficulty < config.MinDifficulty {
|
||||
return nil, fmt.Errorf("%w: maximum difficulty (%d) must be >= minimum difficulty (%d)", ErrInvalidConfig, config.MaxDifficulty, config.MinDifficulty)
|
||||
}
|
||||
|
||||
if config.DefaultDifficulty < config.MinDifficulty || config.DefaultDifficulty > config.MaxDifficulty {
|
||||
return nil, fmt.Errorf("%w: default difficulty (%d) must be between min (%d) and max (%d)", ErrInvalidConfig, config.DefaultDifficulty, config.MinDifficulty, config.MaxDifficulty)
|
||||
}
|
||||
|
||||
if len(config.HMACSecret) == 0 {
|
||||
return nil, fmt.Errorf("%w: HMAC secret cannot be empty", ErrInvalidConfig)
|
||||
}
|
||||
|
||||
if config.ChallengeTTL <= 0 {
|
||||
return nil, fmt.Errorf("%w: challenge TTL must be positive, got %v", ErrInvalidConfig, config.ChallengeTTL)
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
Loading…
Reference in a new issue