ethr-did-registry
Advanced tools
Comparing version 0.0.3 to 1.0.0
@@ -1,3 +0,2 @@ | ||
Apache License | ||
============== | ||
# Apache License | ||
@@ -93,23 +92,23 @@ _Version 2.0, January 2004_ | ||
* **(a)** You must give any other recipients of the Work or Derivative Works a copy of | ||
this License; and | ||
* **(b)** You must cause any modified files to carry prominent notices stating that You | ||
changed the files; and | ||
* **(c)** You must retain, in the Source form of any Derivative Works that You distribute, | ||
all copyright, patent, trademark, and attribution notices from the Source form | ||
of the Work, excluding those notices that do not pertain to any part of the | ||
Derivative Works; and | ||
* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any | ||
Derivative Works that You distribute must include a readable copy of the | ||
attribution notices contained within such NOTICE file, excluding those notices | ||
that do not pertain to any part of the Derivative Works, in at least one of the | ||
following places: within a NOTICE text file distributed as part of the | ||
Derivative Works; within the Source form or documentation, if provided along | ||
with the Derivative Works; or, within a display generated by the Derivative | ||
Works, if and wherever such third-party notices normally appear. The contents of | ||
the NOTICE file are for informational purposes only and do not modify the | ||
License. You may add Your own attribution notices within Derivative Works that | ||
You distribute, alongside or as an addendum to the NOTICE text from the Work, | ||
provided that such additional attribution notices cannot be construed as | ||
modifying the License. | ||
- **(a)** You must give any other recipients of the Work or Derivative Works a copy of | ||
this License; and | ||
- **(b)** You must cause any modified files to carry prominent notices stating that You | ||
changed the files; and | ||
- **(c)** You must retain, in the Source form of any Derivative Works that You distribute, | ||
all copyright, patent, trademark, and attribution notices from the Source form | ||
of the Work, excluding those notices that do not pertain to any part of the | ||
Derivative Works; and | ||
- **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any | ||
Derivative Works that You distribute must include a readable copy of the | ||
attribution notices contained within such NOTICE file, excluding those notices | ||
that do not pertain to any part of the Derivative Works, in at least one of the | ||
following places: within a NOTICE text file distributed as part of the | ||
Derivative Works; within the Source form or documentation, if provided along | ||
with the Derivative Works; or, within a display generated by the Derivative | ||
Works, if and wherever such third-party notices normally appear. The contents of | ||
the NOTICE file are for informational purposes only and do not modify the | ||
License. You may add Your own attribution notices within Derivative Works that | ||
You distribute, alongside or as an addendum to the NOTICE text from the Work, | ||
provided that such additional attribution notices cannot be construed as | ||
modifying the License. | ||
@@ -116,0 +115,0 @@ You may add Your own copyright statement to Your modifications and may provide |
{ | ||
"name": "ethr-did-registry", | ||
"version": "0.0.3", | ||
"description": "A repository storing keys and other data about Decentralized Identifiers (DIDs)", | ||
"main": "build/contracts/EthereumDIDRegistry.json", | ||
"directories": { | ||
"test": "test" | ||
}, | ||
"version": "1.0.0", | ||
"description": "A repository storing keys and other data about Ethereum Decentralized Identifiers (DIDs)", | ||
"main": "./dist/index.js", | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"ethereumjs-tx": "^1.3.4", | ||
"ethereumjs-util": "^5.1.5", | ||
"ganache-cli": "^6.0.3", | ||
"js-sha3": "^0.7.0", | ||
"@babel/core": "7.18.6", | ||
"@babel/preset-env": "7.18.6", | ||
"@babel/preset-typescript": "7.18.6", | ||
"@nomiclabs/hardhat-ethers": "^2.0.6", | ||
"@nomiclabs/hardhat-etherscan": "^3.1.0", | ||
"@nomiclabs/hardhat-waffle": "^2.0.3", | ||
"@semantic-release/changelog": "6.0.1", | ||
"@semantic-release/git": "10.0.1", | ||
"@typechain/ethers-v5": "^10.1.0", | ||
"@typechain/hardhat": "^6.1.2", | ||
"@types/chai": "^4.3.1", | ||
"@types/chai-as-promised": "^7.1.5", | ||
"@types/mocha": "^9.1.1", | ||
"@types/node": "^18.0.3", | ||
"@typescript-eslint/eslint-plugin": "^5.30.5", | ||
"@typescript-eslint/parser": "^5.30.5", | ||
"babel-jest": "28.1.2", | ||
"chai": "^4.3.6", | ||
"chai-as-promised": "^7.1.1", | ||
"dotenv": "^16.0.1", | ||
"eslint": "^8.19.0", | ||
"eslint-config-prettier": "^8.5.0", | ||
"eslint-config-standard": "^17.0.0", | ||
"eslint-plugin-import": "^2.26.0", | ||
"eslint-plugin-n": "^15.2.4", | ||
"eslint-plugin-node": "^11.1.0", | ||
"eslint-plugin-prettier": "^4.2.1", | ||
"eslint-plugin-promise": "^6.0.0", | ||
"ethereum-waffle": "^3.4.4", | ||
"ethereumjs-tx": "^2.1.2", | ||
"ethereumjs-util": "^7.1.5", | ||
"ethers": "^5.6.9", | ||
"hardhat": "^2.9.9", | ||
"hardhat-gas-reporter": "^1.0.8", | ||
"ls": "^0.2.1", | ||
"solhint": "^1.1.10", | ||
"truffle": "^4.1.6", | ||
"truffle-hdwallet-provider": "^0.0.3" | ||
"prettier": "^2.7.1", | ||
"prettier-plugin-solidity": "^1.0.0-beta.13", | ||
"semantic-release": "19.0.3", | ||
"solhint": "^3.3.7", | ||
"solidity-coverage": "^0.7.21", | ||
"ts-node": "^10.8.2", | ||
"typechain": "^8.1.0", | ||
"typescript": "^4.7.4", | ||
"uint8arrays": "^3.0.0" | ||
}, | ||
"scripts": { | ||
"test": "./node_modules/.bin/truffle test", | ||
"lint": "./node_modules/.bin/solhint contracts/EthereumDIDRegistry.sol", | ||
"_deploy": "./node_modules/.bin/truffle migrate --network ", | ||
"deploy-mainnet": "npm run _deploy mainnet", | ||
"deploy-infuranet": "npm run _deploy infuranet", | ||
"deploy-ropsten": "npm run _deploy ropsten", | ||
"deploy-rinkeby": "npm run _deploy rinkeby", | ||
"deploy-kovan": "npm run _deploy kovan", | ||
"deploy-local": "npm run _deploy local", | ||
"deploy-test": "npm run _deploy test" | ||
"build:js": "tsc", | ||
"build:sol": "hardhat compile", | ||
"build": "yarn build:sol && yarn build:js", | ||
"test": "hardhat test", | ||
"lint:js": "npx eslint '**/*.{js,ts}' --fix", | ||
"lint:sol": "npx solhint 'contracts/**/*.sol' --fix", | ||
"lint": "yarn lint:sol && yarn lint:js", | ||
"format": "prettier -w '**/*.{ts,js,json,md}'", | ||
"prepublishOnly": "yarn test && yarn format && yarn lint", | ||
"release": "semantic-release --debug" | ||
}, | ||
"author": "Pelle Braendgaard", | ||
"contributors": [ | ||
"Mircea Nistor <mirceanis@gmail.com>" | ||
], | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/uport-project/ethr-did-registry" | ||
"url": "git@github.com:uport-project/ethr-did-registry.git" | ||
}, | ||
"author": "Pelle Braendgaard <pelle.braendgaard@consensys.net>", | ||
"license": "Apache-2.0" | ||
"files": [ | ||
"artifacts", | ||
"contracts", | ||
"dist", | ||
"typechain-types" | ||
] | ||
} |
293
README.md
@@ -1,77 +0,119 @@ | ||
## Ethereum DID Registry | ||
--- | ||
title: 'Ethereum DID Registry' | ||
index: 0 | ||
category: 'ethr-did-registry' | ||
type: 'reference' | ||
source: 'https://github.com/uport-project/ethr-did-registry/blob/develop/README.md' | ||
--- | ||
This contract allows on and off-chain resolving and management for [DIDs (Decentralized IDentifiers)](https://w3c-ccg.github.io/did-spec/). | ||
# Ethereum DID Registry | ||
A DID is an [Identifier](https://w3c-ccg.github.io/did-spec/#decentralized-identifiers-dids) that allows you to lookup a [DID document](https://w3c-ccg.github.io/did-spec/#did-documents) that can be used to authenticate you and messages created by you. | ||
This library contains the Ethereum contract code that allows the owner of an ethr-did identity to update the attributes | ||
that appear in its did-document. It exposes an API that allows developers to call the contract functions using | ||
Javascript. | ||
It was designed as a way of resolving public keys for off chain authentication, where the public key resolution is handled through the use of decentralized technology. | ||
Use this if you want to interact directly with a deployed registry contract directly, or deploy a copy of the contract | ||
to another Ethereum network. | ||
This contract allows ethereum addresses to present signing information about themselves with no prior registration. It allows them to perform key rotation and specify different keys and services that can be used on it's behalf for both on and off-chain usage. | ||
A DID is an [Identifier](https://w3c.github.io/did-core/#a-simple-example) that allows you to lookup | ||
a [DID document](https://w3c.github.io/did-core/#example-a-simple-did-document) that can be used to authenticate you and | ||
messages created by you. | ||
## Using the registry | ||
It's designed for resolving public keys for off-chain authentication—where the public key resolution is handled by using | ||
decentralized technology. | ||
The DID Registry can be used from javascript as well as directly from other contracts. | ||
This contract allows Ethereum addresses to present signing information about themselves with no prior registration. It | ||
allows them to perform key rotation and specify different keys and services that are used on its behalf for both on and | ||
off-chain usage. | ||
### From javascript | ||
## Contract Deployments | ||
To use the contract we provide truffle artifacts. Once you require the `ethr-did-registry` module you will get an object containing the json. | ||
> WARNING | ||
> Most of these are deployments of version 0.0.3 of the contract and they do not include recent updates. | ||
> Join the discussion as to how to adopt these new changes [on our discord](https://discord.gg/MTeTAwSYe7) | ||
```javascript | ||
const DidRegistryContract = require('ethr-did-registry') | ||
``` | ||
| Network Name | name | chainId | hexChainId | Registry Address | Registry version | | ||
| ------------ | ------- | ---------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | | ||
| Mainnet | mainnet | 1 | 0x1 | [0xdca7ef03e98e0dc2b855be647c39abe984fcf21b](https://etherscan.io/address/0xdca7ef03e98e0dc2b855be647c39abe984fcf21b) | [4278342e](https://github.com/uport-project/ethr-did-registry/commit/4278342e9b1dec0ab4fd63f4bd5536094c4de9f0) | | ||
| Ropsten | ropsten | 3 | 0x3 | [0xdca7ef03e98e0dc2b855be647c39abe984fcf21b](https://ropsten.etherscan.io/address/0xdca7ef03e98e0dc2b855be647c39abe984fcf21b) | [4278342e](https://github.com/uport-project/ethr-did-registry/commit/4278342e9b1dec0ab4fd63f4bd5536094c4de9f0) | | ||
| Rinkeby | rinkeby | 4 | 0x4 | [0xdca7ef03e98e0dc2b855be647c39abe984fcf21b](https://rinkeby.etherscan.io/address/0xdca7ef03e98e0dc2b855be647c39abe984fcf21b) | [4278342e](https://github.com/uport-project/ethr-did-registry/commit/4278342e9b1dec0ab4fd63f4bd5536094c4de9f0) | | ||
| Goerli | goerli | 5 | 0x5 | [0xdca7ef03e98e0dc2b855be647c39abe984fcf21b](https://goerli.etherscan.io/address/0xdca7ef03e98e0dc2b855be647c39abe984fcf21b) | [4278342e](https://github.com/uport-project/ethr-did-registry/commit/4278342e9b1dec0ab4fd63f4bd5536094c4de9f0) | | ||
| Kovan | kovan | 42 | 0x2a | [0xdca7ef03e98e0dc2b855be647c39abe984fcf21b](https://kovan.etherscan.io/address/0xdca7ef03e98e0dc2b855be647c39abe984fcf21b) | [4278342e](https://github.com/uport-project/ethr-did-registry/commit/4278342e9b1dec0ab4fd63f4bd5536094c4de9f0) | | ||
| RSK | rsk | 30 | 0x1e | [0xdca7ef03e98e0dc2b855be647c39abe984fcf21b](https://explorer.rsk.co/address/0xdca7ef03e98e0dc2b855be647c39abe984fcf21b) | [4278342e](https://github.com/uport-project/ethr-did-registry/commit/4278342e9b1dec0ab4fd63f4bd5536094c4de9f0) | | ||
| RSK Testnet | | 31 | 0x1f | [0xdca7ef03e98e0dc2b855be647c39abe984fcf21b](https://explorer.testnet.rsk.co/address/0xdca7ef03e98e0dc2b855be647c39abe984fcf21b) | [4278342e](https://github.com/uport-project/ethr-did-registry/commit/4278342e9b1dec0ab4fd63f4bd5536094c4de9f0) | | ||
| EnergyWeb | ewc | 246 | 0xf6 | [0xe29672f34e92b56c9169f9d485ffc8b9a136bce4](https://explorer.energyweb.org/address/0xE29672f34e92b56C9169f9D485fFc8b9A136BCE4) | [c9063836](https://github.com/uport-project/ethr-did-registry/commit/c90638361a76d247d61ef4e3eb245a78cf587f91) | | ||
| EWC Volta | volta | 73799 | 0x12047 | [0xc15d5a57a8eb0e1dcbe5d88b8f9a82017e5cc4af](https://volta-explorer.energyweb.org/address/0xC15D5A57A8Eb0e1dCBE5D88B8f9a82017e5Cc4AF) | [f4e17ee1](https://github.com/uport-project/ethr-did-registry/commit/f4e17ee1eb558c5a006bab1a04108f27d4e3f0d0) | | ||
| ARTIS tau1 | | 246785 | 0x3c401 | [0xdca7ef03e98e0dc2b855be647c39abe984fcf21b](https://explorer.tau1.artis.network/address/0xdCa7EF03e98e0DC2B855bE647C39ABe984fcF21B) | [4278342e](https://github.com/uport-project/ethr-did-registry/commit/4278342e9b1dec0ab4fd63f4bd5536094c4de9f0) | | ||
| ARTIS sigma1 | | 246529 | 0x3c301 | [0xdca7ef03e98e0dc2b855be647c39abe984fcf21b](https://explorer.sigma1.artis.network/address/0xdCa7EF03e98e0DC2B855bE647C39ABe984fcF21B) | [4278342e](https://github.com/uport-project/ethr-did-registry/commit/4278342e9b1dec0ab4fd63f4bd5536094c4de9f0) | | ||
| Polygon | polygon | 137 | 0x89 | [0xdca7ef03e98e0dc2b855be647c39abe984fcf21b](https://polygonscan.com/address/0xdca7ef03e98e0dc2b855be647c39abe984fcf21b) | [4278342e](https://github.com/uport-project/ethr-did-registry/commit/4278342e9b1dec0ab4fd63f4bd5536094c4de9f0) | | ||
| Polygon test | | 80001 | 0x13881 | [0xdca7ef03e98e0dc2b855be647c39abe984fcf21b](https://mumbai.polygonscan.com/address/0xdca7ef03e98e0dc2b855be647c39abe984fcf21b) | [4278342e](https://github.com/uport-project/ethr-did-registry/commit/4278342e9b1dec0ab4fd63f4bd5536094c4de9f0) | | ||
| Aurora | aurora | 1313161554 | 0x4E454152 | [0x63ed58b671eed12bc1652845ba5b2cdfbff198e0](https://explorer.mainnet.aurora.dev/address/0x63eD58B671EeD12Bc1652845ba5b2CDfBff198e0) | [0ab4f151](https://github.com/uport-project/ethr-did-registry/commit/0ab4f151ddde5b7739b97827c4fb901289f57892) | | ||
You can use `truffle-contract` to utilize these artifacts. | ||
## Using the Registry | ||
The DID Registry can be used from JavaScript as well as directly from other contracts. | ||
To use the contract, we provide hardhat artifacts. Once you require the `ethr-did-registry` module, you will get an | ||
object containing the JSON. | ||
```javascript | ||
const Contract = require('truffle-contract') | ||
let DidReg = Contract(DidRegistryContract) | ||
DidReg.setProvider(web3.currentProvider) | ||
let didReg = DidReg.deployed() | ||
const { EthereumDIDRegistry } = require('ethr-did-registry') | ||
``` | ||
You can also use web3. | ||
You can use [`ethers.js`](https://github.com/ethers-io/ethers.js/) to utilize these artifacts. | ||
```javascript | ||
let networkId = 1 // Mainnet | ||
let DidReg = web3.eth.contract(DidRegistryContract.abi) | ||
let didReg = DidReg.at(DidRegistryContract.networks[networkId].address) | ||
const { ethers } = require('ethers') | ||
const DidReg = new ethers.Contract(registryAddress, EthereumDIDRegistry.abi) | ||
DidReg.connect(yourSignerOrProvider) | ||
``` | ||
## Contract Deployments | ||
|Network|Address| | ||
| --|--| | ||
|Mainnet (id: 1)|[0xdca7ef03e98e0dc2b855be647c39abe984fcf21b](https://etherscan.io/address/0xdca7ef03e98e0dc2b855be647c39abe984fcf21b)| | ||
|Ropsten (id: 3)|[0xdca7ef03e98e0dc2b855be647c39abe984fcf21b](https://ropsten.etherscan.io/address/0xdca7ef03e98e0dc2b855be647c39abe984fcf21b)| | ||
|Rinkeby (id: 4)|[0xdca7ef03e98e0dc2b855be647c39abe984fcf21b](https://rinkeby.etherscan.io/address/0xdca7ef03e98e0dc2b855be647c39abe984fcf21b)| | ||
|Kovan (id: 42)|[0xdca7ef03e98e0dc2b855be647c39abe984fcf21b](https://kovan.etherscan.io/address/0xdca7ef03e98e0dc2b855be647c39abe984fcf21b)| | ||
## On-chain vs. Off-chain | ||
## On-chain vs Off-chain | ||
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. | ||
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 sender of the transaction. | ||
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. | ||
Since each Ethereum transaction must 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 for 3rd party funding | ||
services, or for receivers to pay 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. | ||
These kinds of transactions have to be signed by an actual key pair and thus cannot be used to represent smart contract | ||
based Ethereum accounts. | ||
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. | ||
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. | ||
## Identity Identifier | ||
Any ethereum account regardless of it being a key pair or smart contract based is considered to be an account identifier. | ||
No registration is needed by an identity. | ||
Any Ethereum account regardless of whether it's a key pair or smart contract based is considered to be an account | ||
identifier. | ||
An identity needs no registration. | ||
## Identity Ownership | ||
Each identity has a single address which maintains ultimate control over it. By default each identity is controlled by itself. As ongoing technological and security improvements happen an owner can replace themselves with any other ethereum address, such as an advanced multi signature contract. | ||
There is only ever a single identity owner. More advanced ownership models can be managed through a multi signature contract. | ||
Each identity has a single address which maintains ultimate control over it. By default, each identity is controlled by | ||
itself. As ongoing technological and security improvements occur, an owner can replace themselves with any other | ||
Ethereum address, such as an advanced multi-signature contract. | ||
There is only ever a single identity owner. More advanced ownership models are managed through a multi-signature | ||
contract. | ||
### Looking up Identity Ownership | ||
Ownership of an identity can be verified by calling the `identityOwner(address identity) public view returns(address)` function. This returns the address of the current Identity Owner. | ||
Ownership of identity is verified by calling the `identityOwner(address identity) public view returns(address)` | ||
function. This returns the address of the current Identity Owner. | ||
### Changing Identity Ownership | ||
The account owner can replace themselves at any time, by calling the `changeOwner(address identity, address newOwner)` function. | ||
There is also a version of this function which can be called with an externally created signature, that can be passed to a transaction funding service. | ||
The account owner can replace themselves at any time, by calling the `changeOwner(address identity, address newOwner)` | ||
function. | ||
The externally signed version has the following signature `changeOwnerSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, address newOwner)`. | ||
There is also a version of this function which is called with an externally created signature, that is passed to a | ||
transaction funding service. | ||
The externally signed version has the following | ||
signature `changeOwnerSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, address newOwner)`. | ||
The signature should be signed of the keccak256 hash of the following tightly packed parameters: | ||
@@ -82,30 +124,42 @@ | ||
## Delegates | ||
Delegates are addresses that are delegated for a specific time to perform some sort of function on behalf of an identity. | ||
Delegates are addresses that are delegated for a specific time to perform a function on behalf of an identity. | ||
They can be accessed both on and off-chain. | ||
### Delegate Types | ||
The type of function is simply a string, that is determined by a protocol or application higher up. | ||
Examples: | ||
- ‘did-jwt’ | ||
- ‘raiden’ | ||
- ‘DID-JWT’ | ||
- ‘Raiden’ | ||
### Validity | ||
Delegates expire. Expiration time is application specific and also dependent on the security requirements of the identity owner. | ||
Validity is set using amount of seconds from the time that adding the delegate is set. | ||
Delegates expire. The expiration time is application specific and dependent on the security requirements of the identity | ||
owner. | ||
### Looking up a delegate | ||
You can check if an address is a delegate for an identity using the`validDelegate(address identity, string delegateType, address delegate) returns(bool)` function. This returns true if the address is a valid delegate of the given delegateType. | ||
Validity is set using the number of seconds from the time that adding the delegate is set. | ||
### Adding a delegate | ||
### Looking up a Delegate | ||
You can check to see if an address is a delegate for an identity using | ||
the`validDelegate(address identity, bytes32 delegateType, address delegate) returns(bool)` function. This returns true | ||
if the address is a valid delegate of the given delegateType. | ||
### Adding a Delegate | ||
An identity can assign multiple delegates to manage signing on their behalf for specific purposes. | ||
The account owner can call the `addDelegate(address identity, string delegateType, address delegate, uint validity)` function. | ||
The account owner can call the `addDelegate(address identity, bytes32 delegateType, address delegate, uint validity)` | ||
function. | ||
There is also a version of this function which can be called with an externally created signature, that can be passed to a transaction funding service. | ||
There is also a version of this function which is called with an externally created signature, that is passed to a | ||
transaction funding service. | ||
The externally signed version has the following signature `addDelegateSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, string delegateType, address delegate, uint validity)`. | ||
The externally signed version has the following | ||
signature `addDelegateSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 delegateType, address delegate, uint validity)` | ||
. | ||
@@ -116,9 +170,13 @@ The signature should be signed of the keccak256 hash of the following tightly packed parameters: | ||
### Revoking a delegate | ||
### Revoking a Delegate | ||
A delegate may be manually revoked by calling the `revokeDelegate(address identity, string delegateType, address delegate)` function. | ||
A delegate may be manually revoked by calling | ||
the `revokeDelegate(address identity, string delegateType, address delegate)` function. | ||
There is also a version of this function which can be called with an externally created signature, that can be passed to a transaction funding service. | ||
There is also a version of this function which is called with an externally created signature, that is passed to a | ||
transaction funding service. | ||
The externally signed version has the following signature `revokeDelegateSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, string delegateType, address delegate)`. | ||
The externally signed version has the following | ||
signature `revokeDelegateSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 delegateType, address delegate)` | ||
. | ||
@@ -129,3 +187,3 @@ The signature should be signed of the keccak256 hash of the following tightly packed parameters: | ||
### Enumerating delegates off chain | ||
### Enumerating Delegates Off-chain | ||
@@ -137,3 +195,3 @@ Attributes are stored as `DIDDelegateChanged` events. A `validTo` of 0 indicates a revoked delegate. | ||
address indexed identity, | ||
string delegateType, | ||
bytes32 delegateType, | ||
address delegate, | ||
@@ -145,26 +203,35 @@ uint validTo, | ||
## Adding off-chain attributes | ||
An identity may need to publish some information that is only needed off-chain, but still requires the security benefits of using a blockchain. | ||
## Adding Off-chain Attributes | ||
### Setting attributes | ||
An identity may need to publish some information that is only needed off-chain but still requires the security benefits | ||
of using a blockchain. | ||
These attributes are set using the `setAttribute(address identity, string name, bytes value, uint validity)` function and published using events. | ||
### Setting Attributes | ||
There is also a version of this function which can be called with an externally created signature, that can be passed to a transaction funding service. | ||
These attributes are set using the `setAttribute(address identity, bytes32 name, bytes value, uint validity)` function | ||
and published using events. | ||
The externally signed version has the following signature `setAttributeSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, string name, bytes value, uint validity)`. | ||
There is also a version of this function that is called with an externally created signature, that is passed to a | ||
transaction funding service. | ||
The signature should be signed of the keccak256 hash of the following tightly packed parameters: | ||
The externally signed version has the following | ||
signature `setAttributeSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 name, bytes value, uint validity)` | ||
. | ||
The signature should be signed off the keccak256 hash of the following tightly packed parameters: | ||
`byte(0x19), byte(0), address of registry, nonce[currentOwner], identity, "setAttribute", name, value, validity` | ||
### Revoking attributes | ||
### Revoking Attributes | ||
These attributes are revoked using the `revokeAttribute(address identity, string name, bytes value)` function and published using events. | ||
These attributes are revoked using the `revokeAttribute(address identity, bytes32 name, bytes value)` function and | ||
published using events. | ||
There is also a version of this function which can be called with an externally created signature, that can be passed to a transaction funding service. | ||
There is also a version of this function that is called with an externally created signature, that is passed to a | ||
transaction funding service. | ||
The externally signed version has the following signature `revokeAttributeSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, string name, bytes value)`. | ||
The externally signed version has the following | ||
signature `revokeAttributeSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 name, bytes value)`. | ||
The signature should be signed of the keccak256 hash of the following tightly packed parameters: | ||
The signature should be signed off the keccak256 hash of the following tightly packed parameters: | ||
@@ -180,3 +247,3 @@ `byte(0x19), byte(0), address of registry, nonce[currentOwner], identity, "revokeAttribute", name, value` | ||
address indexed identity, | ||
string name, | ||
bytes32 name, | ||
bytes value, | ||
@@ -188,14 +255,22 @@ uint validTo, | ||
## Efficient lookup of events through linked identity events | ||
### Delegate types and attribute names encoding | ||
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. | ||
For gas cost reasons the names of attributes and types of delegates are fixed size `bytes32` values. In most situations, | ||
this is not a problem since most can be represented by strings shorter than 32 bytes. To get a bytes32 value from them, | ||
the recommended approach is to use the byte array representation of your string and right-pad it to get to 32 bytes. | ||
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. | ||
## Enumerating Linked Identity Events | ||
Each identity has it’s previously changed block stored in the `changed` mapping. | ||
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 to the identity, we can solve this problem | ||
with improved performance. | ||
Each identity has its previously changed block stored in the `changed` mapping. | ||
1. Lookup `previousChange` block for identity | ||
2. Lookup all events for given identity address using web3, but only for the `previousChange` block | ||
3. Do something with event | ||
4. Find `previousChange` from the event and repeat | ||
2. Lookup all events for a given identity address using web3, but only for the `previousChange` block | ||
3. Do something with the event | ||
4. Find `previousChange` from the event and repeat | ||
@@ -206,34 +281,58 @@ Example code | ||
const history = [] | ||
previousChange = await didReg.changed(identity) | ||
while (previousChange) { | ||
const filter = await didReg.allEvents({topics: [identity], fromBlock: previousChange, toBlock: previousChange}) | ||
const events = await getLogs(filter) | ||
previousChange = undefined | ||
for (let event of events) { | ||
history.unshift(event) | ||
previousChange = event.args.previousChange | ||
let prevChange = (await DidReg.changed(identityAddress)).toNumber() | ||
while (prevChange) { | ||
const logs = await ethers.provider.getLogs({ | ||
topics: [null, `0x000000000000000000000000${identityAddress}`], | ||
fromBlock: prevChange, | ||
toBlock: prevChange, | ||
}) | ||
prevChange = 0 | ||
for (const log of logs) { | ||
const logDescription = DidReg.interface.parseLog(log) | ||
history.unshift(logDescription) | ||
prevChange = logDescription.args.previousChange.toNumber() | ||
} | ||
} | ||
} | ||
``` | ||
## Building a DID document for an identity | ||
## Assemble a DID Document | ||
The primary owner key should be looked up using `identityOwner(identity)`. This should be the first of the publicKeys listed. | ||
The full spec describing how to interact with this registry to build a DID document can be found in | ||
the [ehtr-did-resolver](https://github.com/decentralized-identity/ethr-did-resolver/blob/master/doc/did-method-spec.md) | ||
repository. | ||
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. | ||
In short, you would do something like this: | ||
Iterate through `DIDAttributeChanged` events for service entries, encryption public keys and other public names. The attribute names are still to be determined. | ||
The primary owner key should be looked up using `identityOwner(identity)`. This should be the first of the public keys | ||
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, encrypted public keys, and other public names. The | ||
attribute names are still to be determined. | ||
## Deploy contract | ||
First run, | ||
``` | ||
```bash | ||
$ scripts/generateDeployTxs.js | ||
``` | ||
you will get the data needed to deploy as an output from this command. Copy the `senderAddress` and send `cost` amount of ether to this address on the ethereum network you wish to deploy to. Once this tx is confirmed simply send the `rawTx` to the same network. `contractAddress` is the address of the deployed contract. This will be the same on all networks it is deployed to. | ||
## Testing the contracts | ||
You will get the data needed to deploy as an output from this command. | ||
Make sure you have truffle installed then simply run: | ||
Copy the `senderAddress` and send `cost` amount of ether to that address on the Ethereum network you wish to deploy to. | ||
Once this funding transaction is confirmed, simply send the `rawTx` to the same network. | ||
`contractAddress` is the address of the deployed contract. | ||
`chainId` is intentionally not used in the transaction to make it simpler to deploy to the same address on all networks. | ||
## Testing the Contracts | ||
```bash | ||
yarn install | ||
yarn build | ||
yarn test | ||
``` | ||
$ truffle test | ||
``` |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 4 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1441272
34
27253
1
331
44
1
6
2