Files
CosmicClash/server/domain/assignment.go
T
2026-08-31 20:45:29 +01:00

51 lines
2.0 KiB
Go

package domain
import (
"crypto/sha256"
"fmt"
)
type AllocationManifest struct {
AllocationID string
MatchID string
ServerID string
Region string
Build string
Protocol int
Transport string
RosterDigest string
}
type Assignment struct {
Allocation Allocation
Manifest AllocationManifest
Endpoint string
}
var ErrManifestRejected = fmt.Errorf("allocation manifest rejected")
// VerifyAssignment is the assignment-ready gate. A Ready/Allocated process
// has no client-facing endpoint until its signed manifest, allocator binding,
// and hosted endpoint all pass this check.
func VerifyAssignment(allocation Allocation, manifest AllocationManifest, endpoint string, signature []byte, verify func([]byte, []byte) bool) (Assignment, error) {
if allocation.State != ServerAllocated || allocation.AllocationID == "" || allocation.MatchID == "" || allocation.ServerID == "" || endpoint == "" || len(signature) == 0 || verify == nil {
return Assignment{}, ErrManifestRejected
}
if manifest.AllocationID != allocation.AllocationID || manifest.MatchID != allocation.MatchID || manifest.ServerID != allocation.ServerID || manifest.Region != allocation.Region || manifest.Build != allocation.Build || manifest.Protocol != allocation.Protocol || manifest.Transport != allocation.Transport || manifest.RosterDigest == "" {
return Assignment{}, ErrManifestRejected
}
if !verify(manifestBytes(manifest), signature) {
return Assignment{}, ErrManifestRejected
}
return Assignment{Allocation: allocation, Manifest: manifest, Endpoint: endpoint}, nil
}
func manifestBytes(manifest AllocationManifest) []byte {
canonical := fmt.Sprintf("%s\x00%s\x00%s\x00%s\x00%s\x00%d\x00%s\x00%s", manifest.AllocationID, manifest.MatchID, manifest.ServerID, manifest.Region, manifest.Build, manifest.Protocol, manifest.Transport, manifest.RosterDigest)
return []byte(canonical)
}
func ManifestDigest(manifest AllocationManifest) [32]byte {
return sha256.Sum256(manifestBytes(manifest))
}