/ EIPS / eip-1056.md
eip-1056.md
  1  ---
  2  eip: 1056
  3  title: Ethereum Lightweight Identity
  4  author: Pelle Braendgaard <pelle.braendgaard@consensys.net>, Joel Torstensson <oed@consensys.net>
  5  type: Standards Track
  6  category: ERC
  7  discussions-to: https://github.com/ethereum/EIPs/issues/1056
  8  status: Draft
  9  created: 2018-05-03
 10  ---
 11  
 12  ## Simple Summary
 13  
 14  A registry for key and attribute management of lightweight blockchain identities.
 15  
 16  ## Abstract
 17  
 18  This ERC describes a standard for creating and updating identities with a limited use of blockchain resources. An identity can have an unlimited number of `delegates` and `attributes` associated with it. Identity creation is as simple as creating a regular key pair ethereum account, which means that it's free (no gas costs) and all ethereum accounts are valid identities. Furthermore this ERC is fully [DID compliant](https://w3c-ccg.github.io/did-spec/).
 19  
 20  ## Motivation
 21  
 22  As we have been developing identity systems for the last couple of years at uPort it has become apparent that the cost of identity creation is a large issue. The previous Identity proposal [ERC725](https://github.com/ethereum/EIPs/issues/725) faces this exact issue. Our requirements when creating this ERC is that identity creation should be free, and should be possible to do in an offline environment (e.g. refugee scenario). However it must also be possible to rotate keys without changing the primary identifier of the identity. The identity system should be fit to use off-chain as well as on-chain.
 23  
 24  ## Definitions
 25  
 26  * `Identifier`: a piece of data that uniquely identifies the identity, an ethereum address
 27  
 28  * `delegate`: an address that is delegated for a specific time to perform some sort of function on behalf of an identity
 29  
 30  * `delegateType`: the type of a delegate, is determined by a protocol or application higher up
 31    Examples:
 32    
 33    * `did-jwt`
 34    * `raiden`
 35  
 36  * `attribute`: a piece of data associated with the identity
 37  
 38  ## Specification
 39  
 40  This ERC specifies a contract called `EthereumDIDRegistry` that is deployed once and can then be commonly used by everyone.
 41  
 42  ### Identity ownership
 43  
 44  By default an identity is owned by itself, meaning whoever controls the ethereum account with that address. The owner can be updated to a new key pair account or to a multisig account etc.
 45  
 46  #### identityOwner
 47  
 48  Returns the owner of the given identity.
 49  
 50  ```js
 51  function identityOwner(address identity) public view returns(address);
 52  ```
 53  
 54  #### changeOwner
 55  
 56  Sets the owner of the given identity to another ethereum account.
 57  
 58  ```js
 59  function changeOwner(address identity, address newOwner) public;
 60  ```
 61  
 62  #### changeOwnerSigned
 63  
 64  Same as above but with raw signature.
 65  
 66  
 67  ```js
 68  function changeOwnerSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, address newOwner) public;
 69  ```
 70  
 71  ### Delegate management
 72  
 73  Delegates can be used both on- and off-chain. They all have a `delegateType` which can be used to specify the purpose of the delegate.
 74  
 75  #### validDelegate
 76  
 77  Returns true if the given `delegate` is a delegate with type `delegateType` of `identity`.
 78  
 79  ```js
 80  function validDelegate(address identity, bytes32 delegateType, address delegate) public view returns(bool);
 81  ```
 82  
 83  #### addDelegate
 84  
 85  Adds a new delegate with the given type. `validity` indicates the number of seconds that the delegate will be valid for, after which it will no longer be a delegate of `identity`.
 86  
 87  ```js
 88  function addDelegate(address identity, bytes32 delegateType, address delegate, uint validity) public;
 89  ```
 90  
 91  
 92  #### addDelegateSigned
 93  
 94  Same as above but with raw signature.
 95  
 96  
 97  ```js
 98  function addDelegateSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 delegateType, address delegate, uint validity) public;
 99  ```
100  
101  
102  #### revokeDelegate
103  
104  Revokes the given `delegate` for the given `identity`.
105  
106  
107  ```js
108  function revokeDelegate(address identity, bytes32 delegateType, address delegate) public;
109  ```
110  
111  
112  #### revokeDelegateSigned
113  
114  Same as above but with raw signature.
115  
116  
117  ```js
118  function revokeDelegateSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 delegateType, address delegate) public;
119  ```
120  
121  
122  ### Attribute management
123  
124  Attributes contain simple data about the identity. They can be managed only by the owner of the identity.
125  
126  
127  #### setAttribute
128  
129  Sets an attribute with the given `name` and `value`, valid for `validity` seconds.
130  
131  
132  ```js
133  function setAttribute(address identity, bytes32 name, bytes value, uint validity) public;
134  ```
135  
136  
137  #### setAttributeSigned
138  
139  Same as above but with raw signature.
140  
141  
142  ```js
143  function setAttributeSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 name, bytes value, uint validity) public;
144  ```
145  
146  
147  #### revokeAttrubte
148  
149  Revokes an attribute.
150  
151  
152  ```js
153  function revokeAttribute(address identity, bytes32 name, bytes value) public;
154  ```
155  
156  
157  #### revokeAttributeSigned
158  
159  Same as above but with raw signature.
160  
161  
162  ```js
163  function revokeAttributeSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 name, bytes value) public;
164  ```
165  
166  
167  ### Events
168  
169  #### DIDOwnerChanged
170  
171  MUST be triggered when `changeOwner` or `changeOwnerSigned` was successfully called.
172  
173  
174  ```js
175  event DIDOwnerChanged(
176    address indexed identity,
177    address owner,
178    uint previousChange
179  );
180  ```
181  
182  
183  #### DIDDelegateChanged
184  
185  MUST be triggered when a change to a delegate was successfully made.
186  
187  
188  ```js
189  event DIDDelegateChanged(
190    address indexed identity,
191    bytes32 delegateType,
192    address delegate,
193    uint validTo,
194    uint previousChange
195  );
196  ```
197  
198  
199  #### DIDAttritueChanged
200  
201  MUST be triggered when a change to an attribute was successfully made.
202  
203  
204  ```js
205  event DIDAttributeChanged(
206    address indexed identity,
207    bytes32 name,
208    bytes value,
209    uint validTo,
210    uint previousChange
211  );
212  ```
213  
214  
215  ### Efficient lookup of events through linked identity events
216  
217  Contract Events are a useful feature for storing data from smart contracts exclusively for off-chain use.  Unfortunately current ethereum implementations provide a very inefficient lookup mechanism. By using linked events that always link to the previous block with a change for the identity, we can solve this problem with much improved performance. Each identity has its previously changed block stored in the `changed` mapping.
218  
219  
220  
221  1. Lookup `previousChange` block for identity
222  
223  2. Lookup all events for given identity address using web3, but only for the `previousChange` block
224  
225  3. Do something with event
226  
227  4. Find `previousChange` from the event  and repeat
228  
229  
230  
231  Example code:
232  
233  
234  ```js
235  const history = []
236  previousChange = await didReg.changed(identity)
237  while (previousChange) {
238    const filter = await didReg.allEvents({topics: [identity], fromBlock: previousChange, toBlock: previousChange})
239    const events = await getLogs(filter)
240    previousChange = undefined
241    for (let event of events) {
242      history.unshift(event)
243      previousChange = event.args.previousChange
244    }
245  }     
246  ```
247  
248  
249  ### Building a DID document for an identity
250  
251  The primary owner key should be looked up using `identityOwner(identity)`.  This should be the first of the publicKeys listed. Iterate through the `DIDDelegateChanged` events to build a list of additional keys and authentication sections as needed. The list of delegateTypes to include is still to be determined. Iterate through `DIDAttributeChanged` events for service entries, encryption public keys and other public names. The attribute names are still to be determined.
252  
253  
254  ## Rationale
255  
256  For on-chain interactions Ethereum has a built in account abstraction that can be used regardless of whether the account is a smart contract or a key pair. Any transaction has a `msg.sender` as the verified send of the transaction.
257  
258  
259  Since each Ethereum transaction has to be funded, there is a growing trend of on-chain transactions that are authenticated via an externally created signature and not by the actual transaction originator. This allows 3rd party funding services or receiver pays without any fundamental changes to the underlying Ethereum architecture. These kinds of transactions have to be signed by an actual key pair and thus can not be used to represent smart contract based Ethereum accounts.
260  
261  
262  We propose a way of a Smart Contract or regular key pair delegating signing for various purposes to externally managed key pairs. This allows a smart contract to be represented both on-chain as well as off-chain or in payment channels through temporary or permanent delegates.
263  
264  
265  ## Backwards Compatibility
266  
267  All ethereum accounts are valid identities (and DID compatible) using this standard. This means that any wallet provider that uses key pair accounts already supports the bare minimum of this standard, and can implement `delegate` and `attribute` functionality by simply using the `ethr-did` referenced below. As the **DID Auth** standard solidifies it also means that all of these wallets will be compatible with the [DID decentralized login system](https://github.com/decentralized-identity).
268  
269  
270  ## Implementation
271  
272  [ethr-did-registry](https://github.com/uport-project/ethr-did-registry/blob/develop/contracts/EthereumDIDRegistry.sol) (`EthereumDIDRegistry` contract implementation)
273  
274  [ethr-did-resolver](https://github.com/uport-project/ethr-did-resolver) (DID compatible resolver)
275  
276  [ethr-did](https://github.com/uport-project/ethr-did) (javascript library for using the identity)
277  
278  
279  ### Deployment
280  
281  The address for the `EthereumDIDRegistry` is `0xdca7ef03e98e0dc2b855be647c39abe984fcf21b` on Mainnet, Ropsten, Rinkeby and Kovan.
282  
283  ## Copyright
284  
285  Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
286