this repo has no description

cleanup plc operation stuff

Hailey b9831175 4cb0fad5

Changed files
+89 -61
plc
+42 -61
plc/client.go
··· 14 "strings" 15 16 "github.com/bluesky-social/indigo/atproto/crypto" 17 - "github.com/bluesky-social/indigo/atproto/data" 18 "github.com/bluesky-social/indigo/util" 19 ) 20 21 type Client struct { 22 - h *http.Client 23 - 24 service string 25 rotationKey *crypto.PrivateKeyK256 26 - recoveryKey string 27 - pdsHostname string 28 } 29 30 type ClientArgs struct { 31 Service string 32 RotationKey []byte 33 - RecoveryKey string 34 PdsHostname string 35 } 36 ··· 48 h: util.RobustHTTPClient(), 49 service: args.Service, 50 rotationKey: rk, 51 - recoveryKey: args.RecoveryKey, 52 pdsHostname: args.PdsHostname, 53 }, nil 54 } 55 56 - func (c *Client) CreateDID(ctx context.Context, sigkey *crypto.PrivateKeyK256, recovery string, handle string) (string, map[string]any, error) { 57 pubrotkey, err := c.rotationKey.PublicKey() 58 if err != nil { 59 return "", nil, err ··· 61 62 // todo 63 rotationKeys := []string{pubrotkey.DIDKey()} 64 - if c.recoveryKey != "" { 65 - rotationKeys = []string{c.recoveryKey, rotationKeys[0]} 66 - } 67 if recovery != "" { 68 rotationKeys = func(recovery string) []string { 69 newRotationKeys := []string{recovery} ··· 74 }(recovery) 75 } 76 77 - op, err := c.FormatAndSignAtprotoOp(sigkey, handle, rotationKeys, nil) 78 if err != nil { 79 return "", nil, err 80 } 81 82 - did, err := didForCreateOp(op) 83 if err != nil { 84 return "", nil, err 85 } 86 87 - return did, op, nil 88 } 89 90 - func (c *Client) UpdateUserHandle(ctx context.Context, didstr string, nhandle string) error { 91 - return nil 92 - } 93 - 94 - func (c *Client) FormatAndSignAtprotoOp(sigkey *crypto.PrivateKeyK256, handle string, rotationKeys []string, prev *string) (map[string]any, error) { 95 - pubsigkey, err := sigkey.PublicKey() 96 if err != nil { 97 - return nil, err 98 } 99 - 100 - op := map[string]any{ 101 - "type": "plc_operation", 102 - "verificationMethods": map[string]string{ 103 - "atproto": pubsigkey.DIDKey(), 104 - }, 105 - "rotationKeys": rotationKeys, 106 - "alsoKnownAs": []string{"at://" + handle}, 107 - "services": map[string]any{ 108 - "atproto_pds": map[string]string{ 109 - "type": "AtprotoPersonalDataServer", 110 - "endpoint": "https://" + c.pdsHostname, 111 - }, 112 - }, 113 - "prev": prev, 114 - } 115 116 - b, err := data.MarshalCBOR(op) 117 if err != nil { 118 return nil, err 119 } ··· 123 return nil, err 124 } 125 126 - op["sig"] = base64.RawURLEncoding.EncodeToString(sig) 127 128 - return op, nil 129 } 130 131 - func didForCreateOp(op map[string]any) (string, error) { 132 - b, err := data.MarshalCBOR(op) 133 - if err != nil { 134 - return "", err 135 - } 136 - 137 - h := sha256.New() 138 - h.Write(b) 139 - bs := h.Sum(nil) 140 - 141 - b32 := strings.ToLower(base32.StdEncoding.EncodeToString(bs)) 142 - 143 - return "did:plc:" + b32[0:24], nil 144 - } 145 - 146 - func (c *Client) SendOperation(ctx context.Context, did string, op any) error { 147 b, err := json.Marshal(op) 148 if err != nil { 149 return err ··· 162 } 163 defer resp.Body.Close() 164 165 - fmt.Println(resp.StatusCode) 166 - 167 b, err = io.ReadAll(resp.Body) 168 if err != nil { 169 - return err 170 } 171 - 172 - fmt.Println(string(b)) 173 174 return nil 175 }
··· 14 "strings" 15 16 "github.com/bluesky-social/indigo/atproto/crypto" 17 "github.com/bluesky-social/indigo/util" 18 ) 19 20 type Client struct { 21 + h *http.Client 22 service string 23 + pdsHostname string 24 rotationKey *crypto.PrivateKeyK256 25 } 26 27 type ClientArgs struct { 28 Service string 29 RotationKey []byte 30 PdsHostname string 31 } 32 ··· 44 h: util.RobustHTTPClient(), 45 service: args.Service, 46 rotationKey: rk, 47 pdsHostname: args.PdsHostname, 48 }, nil 49 } 50 51 + func (c *Client) CreateDID(ctx context.Context, sigkey *crypto.PrivateKeyK256, recovery string, handle string) (string, *PlcOperation, error) { 52 + pubsigkey, err := sigkey.PublicKey() 53 + if err != nil { 54 + return "", nil, err 55 + } 56 + 57 pubrotkey, err := c.rotationKey.PublicKey() 58 if err != nil { 59 return "", nil, err ··· 61 62 // todo 63 rotationKeys := []string{pubrotkey.DIDKey()} 64 if recovery != "" { 65 rotationKeys = func(recovery string) []string { 66 newRotationKeys := []string{recovery} ··· 71 }(recovery) 72 } 73 74 + op := PlcOperation{ 75 + Type: "plc_operation", 76 + VerificationMethods: map[string]string{ 77 + "atproto": pubsigkey.DIDKey(), 78 + }, 79 + RotationKeys: rotationKeys, 80 + AlsoKnownAs: []string{ 81 + "at://" + handle, 82 + }, 83 + Services: map[string]PlcOperationService{ 84 + "atproto_pds": { 85 + Type: "AtprotoPersonalDataServer", 86 + Endpoint: "https://" + c.pdsHostname, 87 + }, 88 + }, 89 + Prev: nil, 90 + } 91 + 92 + signed, err := c.FormatAndSignAtprotoOp(sigkey, op) 93 if err != nil { 94 return "", nil, err 95 } 96 97 + did, err := didFromOp(signed) 98 if err != nil { 99 return "", nil, err 100 } 101 102 + return did, &op, nil 103 } 104 105 + func didFromOp(op *PlcOperation) (string, error) { 106 + b, err := op.MarshalCBOR() 107 if err != nil { 108 + return "", err 109 } 110 + s := sha256.Sum256(b) 111 + b32 := strings.ToLower(base32.StdEncoding.EncodeToString(s[:])) 112 + return "did:plc:" + b32[0:24], nil 113 + } 114 115 + func (c *Client) FormatAndSignAtprotoOp(sigkey *crypto.PrivateKeyK256, op PlcOperation) (*PlcOperation, error) { 116 + b, err := op.MarshalCBOR() 117 if err != nil { 118 return nil, err 119 } ··· 123 return nil, err 124 } 125 126 + op.Sig = base64.RawURLEncoding.EncodeToString(sig) 127 128 + return &op, nil 129 } 130 131 + func (c *Client) SendOperation(ctx context.Context, did string, op *PlcOperation) error { 132 b, err := json.Marshal(op) 133 if err != nil { 134 return err ··· 147 } 148 defer resp.Body.Close() 149 150 b, err = io.ReadAll(resp.Body) 151 if err != nil { 152 + return fmt.Errorf("error sending operation. status code: %d, response: %s", resp.StatusCode, string(b)) 153 } 154 155 return nil 156 }
+47
plc/types.go
···
··· 1 + package plc 2 + 3 + import ( 4 + "encoding/json" 5 + 6 + "github.com/bluesky-social/indigo/atproto/data" 7 + cbg "github.com/whyrusleeping/cbor-gen" 8 + ) 9 + 10 + type PlcOperation struct { 11 + Type string `json:"type"` 12 + VerificationMethods map[string]string `json:"verificationMethods"` 13 + RotationKeys []string `json:"rotationKeys"` 14 + AlsoKnownAs []string `json:"alsoKnownAs"` 15 + Services map[string]PlcOperationService `json:"services"` 16 + Prev *string `json:"prev"` 17 + Sig string `json:"sig,omitempty"` 18 + } 19 + 20 + type PlcOperationService struct { 21 + Type string `json:"type"` 22 + Endpoint string `json:"endpoint"` 23 + } 24 + 25 + // This is kinda gross. We could just use cborgen i suppose? 26 + func (po *PlcOperation) MarshalCBOR() ([]byte, error) { 27 + if po == nil { 28 + return cbg.CborNull, nil 29 + } 30 + 31 + b, err := json.Marshal(po) 32 + if err != nil { 33 + return nil, err 34 + } 35 + 36 + var m map[string]any 37 + if err := json.Unmarshal(b, &m); err != nil { 38 + return nil, err 39 + } 40 + 41 + b, err = data.MarshalCBOR(m) 42 + if err != nil { 43 + return nil, err 44 + } 45 + 46 + return b, nil 47 + }