aboutsummaryrefslogtreecommitdiff
path: root/internal/state
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-26 15:41:45 -0800
committerFuwn <[email protected]>2026-02-26 15:41:45 -0800
commitfec9114caaa7d274e524793d5eb0cf2ef2c5af11 (patch)
tree0897394ccdfaf6633e1a4ca8eb02bff49bb93c00 /internal/state
parentfeat: add read-only PLC API compatibility endpoints (diff)
downloadplutia-test-fec9114caaa7d274e524793d5eb0cf2ef2c5af11.tar.xz
plutia-test-fec9114caaa7d274e524793d5eb0cf2ef2c5af11.zip
feat: Apply Iku formatting
Diffstat (limited to 'internal/state')
-rw-r--r--internal/state/engine.go38
1 files changed, 37 insertions, 1 deletions
diff --git a/internal/state/engine.go b/internal/state/engine.go
index 4ecdaca..0f5caad 100644
--- a/internal/state/engine.go
+++ b/internal/state/engine.go
@@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"time"
-
"github.com/Fuwn/plutia/internal/config"
"github.com/Fuwn/plutia/internal/storage"
"github.com/Fuwn/plutia/internal/types"
@@ -21,41 +20,55 @@ func New(store storage.Store, mode string) *Engine {
func (e *Engine) Apply(op types.ParsedOperation, blockRef *types.BlockRefV1) error {
existing, ok, err := e.store.GetState(op.DID)
+
if err != nil {
return fmt.Errorf("load state: %w", err)
}
+
var prior *types.StateV1
+
if ok {
prior = &existing
}
+
next, err := ComputeNextState(op, prior)
+
if err != nil {
return err
}
+
if pebbleStore, ok := e.store.(*storage.PebbleStore); ok {
includeOpRef := e.mode == config.ModeMirror && blockRef != nil
+
if err := pebbleStore.ApplyOperationBatch(next, blockRef, includeOpRef); err != nil {
return fmt.Errorf("apply operation batch: %w", err)
}
+
return nil
}
+
if err := e.store.PutState(next); err != nil {
return fmt.Errorf("put state: %w", err)
}
+
if err := e.store.SetChainHead(op.DID, op.Sequence); err != nil {
return fmt.Errorf("set chain head: %w", err)
}
+
if err := e.store.AddDIDSequence(op.DID, op.Sequence); err != nil {
return fmt.Errorf("append did sequence: %w", err)
}
+
if e.mode == config.ModeMirror && blockRef != nil {
if err := e.store.PutOpSeqRef(op.Sequence, *blockRef); err != nil {
return fmt.Errorf("put opseq ref: %w", err)
}
}
+
if err := e.store.SetGlobalSeq(op.Sequence); err != nil {
return fmt.Errorf("set global seq: %w", err)
}
+
return nil
}
@@ -64,12 +77,16 @@ func ComputeNextState(op types.ParsedOperation, existing *types.StateV1) (types.
if existing.ChainTipHash == op.CID {
return *existing, nil
}
+
return types.StateV1{}, fmt.Errorf("non-monotonic sequence for %s: got %d <= %d", op.DID, op.Sequence, existing.LatestOpSeq)
}
+
doc, err := materializeDIDDocument(op.DID, op.Payload)
+
if err != nil {
return types.StateV1{}, err
}
+
next := types.StateV1{
Version: 1,
DID: op.DID,
@@ -79,9 +96,11 @@ func ComputeNextState(op types.ParsedOperation, existing *types.StateV1) (types.
UpdatedAt: time.Now().UTC(),
}
next.RotationKeys = extractRotationKeys(op.Payload)
+
if len(next.RotationKeys) == 0 && existing != nil {
next.RotationKeys = append([]string(nil), existing.RotationKeys...)
}
+
return next, nil
}
@@ -89,31 +108,39 @@ func materializeDIDDocument(did string, payload map[string]any) ([]byte, error)
for _, k := range []string{"did_document", "didDoc", "document", "didDocument"} {
if v, ok := payload[k]; ok {
b, err := json.Marshal(v)
+
if err != nil {
return nil, fmt.Errorf("marshal did document field %s: %w", k, err)
}
+
return types.CanonicalizeJSON(b)
}
}
+
if v, ok := payload["alsoKnownAs"]; ok {
doc := map[string]any{
"id": did,
"alsoKnownAs": v,
}
b, err := json.Marshal(doc)
+
if err != nil {
return nil, fmt.Errorf("marshal derived did document: %w", err)
}
+
return types.CanonicalizeJSON(b)
}
doc := map[string]any{"id": did}
+
if typ, _ := payload["type"].(string); typ == "plc_tombstone" || typ == "tombstone" {
doc["deactivated"] = true
}
+
if handle, ok := payload["handle"].(string); ok && handle != "" {
doc["alsoKnownAs"] = []string{"at://" + handle}
}
+
if serviceEndpoint, ok := payload["service"].(string); ok && serviceEndpoint != "" {
doc["service"] = []map[string]any{
{
@@ -123,6 +150,7 @@ func materializeDIDDocument(did string, payload map[string]any) ([]byte, error)
},
}
}
+
if signingKey, ok := payload["signingKey"].(string); ok && signingKey != "" {
doc["verificationMethod"] = []map[string]any{
{
@@ -134,10 +162,13 @@ func materializeDIDDocument(did string, payload map[string]any) ([]byte, error)
}
doc["authentication"] = []string{"#atproto"}
}
+
b, err := json.Marshal(doc)
+
if err != nil {
return nil, fmt.Errorf("marshal synthesized did document: %w", err)
}
+
return types.CanonicalizeJSON(b)
}
@@ -148,9 +179,11 @@ func extractRotationKeys(payload map[string]any) []string {
if v == "" {
return
}
+
if _, ok := seen[v]; ok {
return
}
+
seen[v] = struct{}{}
keys = append(keys, v)
}
@@ -162,11 +195,14 @@ func extractRotationKeys(payload map[string]any) []string {
}
}
}
+
if recovery, ok := payload["recoveryKey"].(string); ok {
add(recovery)
}
+
if signing, ok := payload["signingKey"].(string); ok {
add(signing)
}
+
return keys
}