1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package plc
import (
"maps"
"sort"
"strings"
)
var didContext = []string{
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/multikey/v1",
}
func ResolveDocument(did string, current []LogEntry) *DIDDocument {
if len(current) == 0 {
return nil
}
if current[len(current)-1].Operation.Type == TypeTombstone {
return nil
}
verificationMethods := map[string]string{}
alsoKnownAs := []string{}
services := map[string]Service{}
for _, entry := range current {
op := entry.Operation
switch op.Type {
case TypeOperation:
maps.Copy(verificationMethods, op.VerificationMethods)
alsoKnownAs = dedupe(append(alsoKnownAs, op.AlsoKnownAs...))
maps.Copy(services, op.Services)
case TypeCreate:
next := map[string]string{"atproto": op.SigningKey}
maps.Copy(next, verificationMethods)
verificationMethods = next
if op.Handle != "" {
alsoKnownAs = dedupe(append(alsoKnownAs, op.Handle))
}
nextServices := map[string]Service{
"atproto_pds": {Type: "AtprotoPersonalDataServer", Endpoint: op.Service},
}
maps.Copy(nextServices, services)
services = nextServices
}
}
doc := &DIDDocument{Context: append([]string{}, didContext...), ID: did}
if len(alsoKnownAs) > 0 {
doc.AlsoKnownAs = alsoKnownAs
}
vmKeys := make([]string, 0, len(verificationMethods))
for k := range verificationMethods {
vmKeys = append(vmKeys, k)
}
sort.Strings(vmKeys)
for _, id := range vmKeys {
key := verificationMethods[id]
key = strings.TrimPrefix(key, "did:key:")
doc.VerificationMethod = append(doc.VerificationMethod, VerificationMethod{
ID: "#" + id,
Type: "Multikey",
Controller: did,
PublicKeyMultibase: key,
})
}
svcKeys := make([]string, 0, len(services))
for k := range services {
svcKeys = append(svcKeys, k)
}
sort.Strings(svcKeys)
for _, id := range svcKeys {
s := services[id]
doc.Service = append(doc.Service, DIDService{
ID: "#" + id,
Type: s.Type,
ServiceEndpoint: s.Endpoint,
})
}
return doc
}
func dedupe(in []string) []string {
seen := make(map[string]struct{}, len(in))
out := make([]string, 0, len(in))
for _, v := range in {
if _, ok := seen[v]; ok {
continue
}
seen[v] = struct{}{}
out = append(out, v)
}
return out
}