All Downloads are FREE. Search and download functionalities are using the official Maven repository.

convex.lab.did.cvx Maven / Gradle / Ivy

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)))




© 2015 - 2024 Weber Informatics LLC | Privacy Policy