122 lines
3.7 KiB
Go
122 lines
3.7 KiB
Go
package controller
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"hash-of-wisdom/internal/pow/challenge"
|
|
"hash-of-wisdom/internal/protocol"
|
|
"hash-of-wisdom/internal/quotes"
|
|
)
|
|
|
|
// WisdomService defines the interface for the wisdom service
|
|
type WisdomService interface {
|
|
GenerateChallenge(ctx context.Context, resource string) (*challenge.Challenge, error)
|
|
VerifySolution(ctx context.Context, solution *challenge.Solution) error
|
|
GetQuote(ctx context.Context) (*quotes.Quote, error)
|
|
}
|
|
|
|
// WisdomController handles the Word of Wisdom protocol flow
|
|
type WisdomController struct {
|
|
wisdomService WisdomService
|
|
codec *protocol.Codec
|
|
}
|
|
|
|
// NewWisdomController creates a new wisdom protocol controller
|
|
func NewWisdomController(wisdomService WisdomService) *WisdomController {
|
|
return &WisdomController{
|
|
wisdomService: wisdomService,
|
|
codec: protocol.NewCodec(),
|
|
}
|
|
}
|
|
|
|
// HandleMessage processes a protocol message and returns a response
|
|
func (c *WisdomController) HandleMessage(ctx context.Context, msg *protocol.Message) (*protocol.Message, error) {
|
|
switch msg.Type {
|
|
case protocol.ChallengeRequest:
|
|
return c.handleChallengeRequest(ctx, msg)
|
|
case protocol.SolutionRequest:
|
|
return c.handleSolutionRequest(ctx, msg)
|
|
default:
|
|
return c.createErrorResponse(protocol.ErrMalformedMessage,
|
|
fmt.Sprintf("unsupported message type: 0x%02x", msg.Type))
|
|
}
|
|
}
|
|
|
|
// handleChallengeRequest processes challenge requests
|
|
func (c *WisdomController) handleChallengeRequest(ctx context.Context, _ *protocol.Message) (*protocol.Message, error) {
|
|
challenge, err := c.wisdomService.GenerateChallenge(ctx, "quotes")
|
|
if err != nil {
|
|
return c.createErrorResponse(protocol.ErrServerError, "failed to generate challenge")
|
|
}
|
|
|
|
// Protocol requires direct challenge JSON (not wrapped)
|
|
payload := (*protocol.ChallengeResponsePayload)(challenge)
|
|
jsonData, err := json.Marshal(payload)
|
|
if err != nil {
|
|
return c.createErrorResponse(protocol.ErrServerError, "failed to marshal challenge")
|
|
}
|
|
|
|
return &protocol.Message{
|
|
Type: protocol.ChallengeResponse,
|
|
Payload: jsonData,
|
|
}, nil
|
|
}
|
|
|
|
// handleSolutionRequest processes solution requests
|
|
func (c *WisdomController) handleSolutionRequest(ctx context.Context, msg *protocol.Message) (*protocol.Message, error) {
|
|
// Parse solution request
|
|
var solutionReq protocol.SolutionRequestPayload
|
|
if err := json.Unmarshal(msg.Payload, &solutionReq); err != nil {
|
|
return c.createErrorResponse(protocol.ErrMalformedMessage, "invalid solution format")
|
|
}
|
|
|
|
// Create solution object
|
|
solution := &challenge.Solution{
|
|
Challenge: solutionReq.Challenge,
|
|
Nonce: solutionReq.Nonce,
|
|
}
|
|
|
|
// Verify solution
|
|
if err := c.wisdomService.VerifySolution(ctx, solution); err != nil {
|
|
return c.createErrorResponse(protocol.ErrInvalidSolution, "solution verification failed")
|
|
}
|
|
|
|
// Get quote
|
|
quote, err := c.wisdomService.GetQuote(ctx)
|
|
if err != nil {
|
|
return c.createErrorResponse(protocol.ErrServerError, "failed to get quote")
|
|
}
|
|
|
|
// Protocol requires direct quote JSON (not wrapped)
|
|
payload := (*protocol.QuoteResponsePayload)(quote)
|
|
jsonData, err := json.Marshal(payload)
|
|
if err != nil {
|
|
return c.createErrorResponse(protocol.ErrServerError, "failed to marshal quote")
|
|
}
|
|
|
|
return &protocol.Message{
|
|
Type: protocol.QuoteResponse,
|
|
Payload: jsonData,
|
|
}, nil
|
|
}
|
|
|
|
// createErrorResponse creates a protocol error response
|
|
func (c *WisdomController) createErrorResponse(code, message string) (*protocol.Message, error) {
|
|
errorPayload := &protocol.ErrorResponsePayload{
|
|
Code: code,
|
|
Message: message,
|
|
}
|
|
|
|
jsonData, err := json.Marshal(errorPayload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to marshal error: %w", err)
|
|
}
|
|
|
|
return &protocol.Message{
|
|
Type: protocol.ErrorResponse,
|
|
Payload: jsonData,
|
|
}, nil
|
|
}
|