convex.lab.did.cvx Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of convex-core Show documentation
Show all versions of convex-core Show documentation
Convex core libraries and common utilities
The newest version!
'convex.did
;; This is an implementation of the W3C DID specification for a Verifiable Data Registry on Convex
;;
;; This registry can be used to implement a DID method such as "did:convex:101"
;;
;; Notes
;; - IDs are sequentially allocated integers. mapping human readable names to ID is possible but outside of scope of this library
;; - The required operations Create, Read, Update and Deactivate are implemeted on-chain
;; - We regard a nil DDO as deactivated
;; - Records are internally stored as a Vector with the following elements:
;; 0: ddo-document = A string (or nil) containing the DDO
;; 1: controller = address (or trust monitor) to authorise DID updates
;; 2: created = timestamp of DID creation
;; 3: updated = timestamp of last update
;; 4: accounts = Set of accounts authorised to act on behalf of this identity
;;
;; DIDs can be used as trust monitors, in the form [did-actor-address id] in which case
;; they allow access to the DID's authorised account Set.
(import convex.trust :as trust)
;; A map of [ID -> record vectors]
(def dids {})
;; A counter for unique DID IDs, allocated sequentially
(def counter 1)
(defn
^{:callable true
:doc {:description "Gets a DID document for a given account. Returns nil if ID is invalid or DDO does not exist."
:signature [{:params [addr]}]}}
read
[id]
(if-let [rec (get dids id)]
(nth rec 0)))
(defn
^{:callable true
:doc {:description "Creates a new DID. Controller will be *caller* unless otherwise specified."
:signature [{:params []}
{:params [controller]}]}}
create
([]
(recur *caller*))
([controller]
(let [id counter
controller (if (callable? controller) controller (fail :ARGUMENT "Invalid controller"))
rec ["" controller *timestamp* *timestamp* nil]]
(set! dids (assoc dids id rec))
(set! counter (inc counter))
id)))
(defn
^{:callable true
:doc {:description "Updates a DDO for a DID. DDO can be a String, or nil to deactivate"
:signature [{:params [id ddo]}]}}
update
([ddo]
(recur *scope* ddo))
([id ddo]
(assert (or (nil? ddo) (str? ddo)))
(let [rec (get dids id)
_ (or rec (fail :STATE "Invalid DID"))
cont (get rec 1)
_ (or (trust/trusted? cont *caller* :update id) (fail :TRUST "Unauthorised"))
rec (assoc rec 0 ddo) ;; update DDO
rec (assoc rec 3 *timestamp*) ;; update timestamp
]
(set! dids (assoc dids id rec))
rec)))
(defn
^{:callable true
:doc {:description "Authorises a set of accounts for this DID. May be nil."
:signature [{:params [id auth-set]}]}}
authorise
([auth-set]
(recur *scope* auth-set))
([id auth-set]
(or (nil? auth-set) (set? auth-set) (fail "auth-set must be nil or a set of addresses"))
(let [rec (get dids id)
_ (or rec (fail :TRUST "Invalid or missing DID"))
cont (get rec 1)
_ (or (trust/trusted? cont *caller* :update id) (fail :TRUST "Unauthorised"))
rec (assoc rec 4 auth-set) ;; update Authorised account set
rec (assoc rec 3 *timestamp*) ;; update timestamp
]
(set! dids (assoc dids id rec))
rec)))
(defn
^{:callable true
:doc {:description "Sets the contoller for a DID."
:signature [{:params [id auth-set]}]}}
change-control
([controller]
(if (nil? *scope*)
(fail :TRUST "Changing controller of DID registry not supported")
(recur *scope* controller)))
([id controller]
(let [rec (get dids id)
_ (or rec (fail :TRUST "Invalid or missing DID"))
cont (get rec 1)
_ (or (trust/trusted? cont *caller* :control id) (fail :TRUST "Unauthorised"))
rec (assoc rec 1 controller) ;; update Authorised account set
rec (assoc rec 3 *timestamp*) ;; update timestamp
]
(set! dids (assoc dids id rec))
rec)))
(defn check-trusted?
^{:callable true
:doc {:description "Trust monitor for DID. Checks if subject is authorised by the DID, where the DID is provided either via a scoped call or the object parameter."
:signature [{:params [subject action object]}]}}
[subject action object]
(let [id (or *scope* object)
rec (get dids id)]
(boolean (and
rec ;; not nil
(nth rec 0) ;; not deactivated
(address? subject)
(contains-key? (nth rec 4)
(address subject))))))
(defn
^{:callable true
:doc {:description "Deactivates a DID."
:signature [{:params [id]}]}}
deactivate
([]
(update *scope* nil))
([id]
(update id nil)))