87 lines
2 KiB
Go
87 lines
2 KiB
Go
|
|
package service
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"errors"
|
||
|
|
"fmt"
|
||
|
|
"hash-of-wisdom/internal/pow/challenge"
|
||
|
|
"hash-of-wisdom/internal/quotes"
|
||
|
|
)
|
||
|
|
|
||
|
|
var (
|
||
|
|
ErrResourceRequired = errors.New("resource is required")
|
||
|
|
ErrUnsupportedResource = errors.New("unsupported resource")
|
||
|
|
ErrSolutionRequired = errors.New("solution is required")
|
||
|
|
ErrInvalidChallenge = errors.New("invalid challenge")
|
||
|
|
ErrInvalidSolution = errors.New("invalid proof of work solution")
|
||
|
|
)
|
||
|
|
|
||
|
|
type ChallengeGenerator interface {
|
||
|
|
GenerateChallenge() (*challenge.Challenge, error)
|
||
|
|
}
|
||
|
|
|
||
|
|
type ChallengeVerifier interface {
|
||
|
|
VerifyChallenge(ch *challenge.Challenge) error
|
||
|
|
}
|
||
|
|
|
||
|
|
type QuoteService interface {
|
||
|
|
GetRandomQuote(ctx context.Context) (*quotes.Quote, error)
|
||
|
|
}
|
||
|
|
|
||
|
|
type WisdomService struct {
|
||
|
|
challengeGenerator ChallengeGenerator
|
||
|
|
challengeVerifier ChallengeVerifier
|
||
|
|
quoteService QuoteService
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewWisdomService(
|
||
|
|
generator ChallengeGenerator,
|
||
|
|
verifier ChallengeVerifier,
|
||
|
|
quoteService QuoteService,
|
||
|
|
) *WisdomService {
|
||
|
|
return &WisdomService{
|
||
|
|
challengeGenerator: generator,
|
||
|
|
challengeVerifier: verifier,
|
||
|
|
quoteService: quoteService,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *WisdomService) GenerateChallenge(ctx context.Context, resource string) (*challenge.Challenge, error) {
|
||
|
|
if resource == "" {
|
||
|
|
return nil, ErrResourceRequired
|
||
|
|
}
|
||
|
|
|
||
|
|
if resource != "quotes" {
|
||
|
|
return nil, ErrUnsupportedResource
|
||
|
|
}
|
||
|
|
|
||
|
|
ch, err := s.challengeGenerator.GenerateChallenge()
|
||
|
|
if err != nil {
|
||
|
|
return nil, fmt.Errorf("failed to generate challenge: %w", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
return ch, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *WisdomService) VerifySolution(ctx context.Context, solution *challenge.Solution) error {
|
||
|
|
if solution == nil {
|
||
|
|
return ErrSolutionRequired
|
||
|
|
}
|
||
|
|
|
||
|
|
// Verify challenge authenticity and expiration
|
||
|
|
if err := s.challengeVerifier.VerifyChallenge(&solution.Challenge); err != nil {
|
||
|
|
return fmt.Errorf("%w: %v", ErrInvalidChallenge, err)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Verify PoW solution
|
||
|
|
if !solution.Verify() {
|
||
|
|
return ErrInvalidSolution
|
||
|
|
}
|
||
|
|
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *WisdomService) GetQuote(ctx context.Context) (*quotes.Quote, error) {
|
||
|
|
return s.quoteService.GetRandomQuote(ctx)
|
||
|
|
}
|