Skip to content

Commit

Permalink
feat: upgrade to latest did core spec (decentralized-identity#99) (de…
Browse files Browse the repository at this point in the history
…centralized-identity#109) (decentralized-identity#111)

* feat: refactor configuration options, add `chainID`
* fix: improve `kid` stability during attribute changes
* chore: cleanup in tests and local dependencies
* test(coverage): improve test coverage
* refactor(style): enable linting using `eslint`
* refactor: isolate some of the type definitions
* fix: test that checksum address resolves to identical DID document (decentralized-identity#105)
* fix: setAttribute with sigAuth adds key to authentication section (decentralized-identity#95)
* feat: enable base58 encoding for keys (decentralized-identity#106)(decentralized-identity#99)
* refactor: group types, defaults, and helper methods
* fix: add support for deactivated DIDs (decentralized-identity#83)(decentralized-identity#85)
* fix(deps): bump did-resolver version
* fix: update the default `@context` to be LD compatible (decentralized-identity#99)
* docs: update readme and spec to reflect reality and current DID spec compliance (decentralized-identity#99)
* fix: rename `publicKey` to `verificationMethod` (decentralized-identity#99)
* fix: rename `ethereumAddress` to `blockchainAccountId` (decentralized-identity#99)
* feat: no more errors thrown during resolution.

fixes decentralized-identity#83
closes decentralized-identity#85
fixes decentralized-identity#95
fixes decentralized-identity#105
closes decentralized-identity#106
fixes decentralized-identity#99

BREAKING CHANGE: The return type is `DIDResolutionResult` which wraps a `DIDDocument`.
BREAKING CHANGE: No errors are thrown during DID resolution. Please check `result.didResolutionMetadata.error` instead.
BREAKING CHANGE: This DID core spec requirement will break for users expecting `publicKey`, `ethereumAddress`, `Secp256k1VerificationKey2018` entries in the DID document. They are replaced with `verificationMethod`, `blockchainAccountId` and `EcdsaSecp256k1VerificationKey2019` and `EcdsaSecp256k1RecoveryMethod2020` depending on the content.
  • Loading branch information
mirceanis authored Mar 15, 2021
1 parent 5534554 commit 2a023b1
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 489 deletions.
3 changes: 0 additions & 3 deletions commitlint.config.js

This file was deleted.

441 changes: 0 additions & 441 deletions package-lock.json

Large diffs are not rendered by default.

35 changes: 16 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,29 +53,26 @@
"test-with-coverage": "jest --coverage && codecov"
},
"devDependencies": {
"@babel/core": "^7.13.10",
"@babel/preset-env": "^7.13.10",
"@babel/preset-typescript": "^7.13.0",
"@commitlint/cli": "^12.0.1",
"@commitlint/config-conventional": "^12.0.1",
"@babel/core": "7.13.10",
"@babel/preset-env": "7.13.10",
"@babel/preset-typescript": "7.13.0",
"@semantic-release/changelog": "5.0.1",
"@semantic-release/git": "9.0.0",
"@types/jest": "^26.0.20",
"@typescript-eslint/eslint-plugin": "^4.17.0",
"@typescript-eslint/parser": "^4.17.0",
"babel-jest": "^26.6.3",
"@types/jest": "26.0.20",
"@typescript-eslint/eslint-plugin": "4.17.0",
"@typescript-eslint/parser": "4.17.0",
"babel-jest": "26.6.3",
"codecov": "3.8.1",
"eslint": "^7.21.0",
"eslint-config-prettier": "^8.1.0",
"ganache-cli": "^6.12.2",
"husky": "^5.1.3",
"eslint": "7.21.0",
"eslint-config-prettier": "8.1.0",
"ganache-cli": "6.12.2",
"jest": "26.6.3",
"microbundle": "^0.13.0",
"prettier": "^2.2.1",
"pretty-quick": "^3.1.0",
"semantic-release": "^17.4.1",
"typescript": "^4.2.3",
"uint8arrays": "^2.1.3"
"microbundle": "0.13.0",
"prettier": "2.2.1",
"pretty-quick": "3.1.0",
"semantic-release": "17.4.1",
"typescript": "4.2.3",
"uint8arrays": "2.1.3"
},
"dependencies": {
"@ethersproject/abi": "^5.0.13",
Expand Down
36 changes: 36 additions & 0 deletions src/__tests__/errors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Resolver } from 'did-resolver'
import { getResolver } from '../resolver'

describe('error handling', () => {
const didResolver = new Resolver(
getResolver({
networks: [{ name: 'example', rpcUrl: 'example.com' }],
})
)

it('rejects invalid DID', async () => {
expect.assertions(1)
await expect(didResolver.resolve('did:ethr:2nQtiQG6Cgm1GYTBaaKAgr76uY7iSexUkqX')).resolves.toEqual({
didDocument: null,
didDocumentMetadata: {},
didResolutionMetadata: {
error: 'invalidDid',
message: 'Not a valid did:ethr: 2nQtiQG6Cgm1GYTBaaKAgr76uY7iSexUkqX',
},
})
})

it('rejects resolution on unconfigured network', async () => {
expect.assertions(1)
await expect(
didResolver.resolve('did:ethr:zrx:0x03fdd57adec3d438ea237fe46b33ee1e016eda6b585c3e27ea66686c2ea5358479')
).resolves.toEqual({
didDocument: null,
didDocumentMetadata: {},
didResolutionMetadata: {
error: 'unknownNetwork',
message: 'The DID resolver does not have a configuration for network: zrx',
},
})
})
})
9 changes: 0 additions & 9 deletions src/__tests__/networks.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,5 @@ describe('ethrResolver (alt-chains)', () => {
},
})
})

it('throws on resolving unconfigured network', async () => {
expect.assertions(1)
const ethr = getResolver({ networks: [{ name: 'rsk', rpcUrl: 'https://did.rsk.co:4444' }] })
const resolver = new Resolver(ethr)
await expect(
resolver.resolve('did:ethr:zrx:0x03fdd57adec3d438ea237fe46b33ee1e016eda6b585c3e27ea66686c2ea5358479')
).rejects.toThrowError('unknown_network: The DID resolver does not have a configuration for network: zrx')
})
})
})
9 changes: 0 additions & 9 deletions src/__tests__/resolver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -979,13 +979,4 @@ describe('ethrResolver', () => {
})
})
})

describe('error handling', () => {
it('rejects promise', async () => {
expect.assertions(1)
await expect(didResolver.resolve('did:ethr:2nQtiQG6Cgm1GYTBaaKAgr76uY7iSexUkqX')).rejects.toEqual(
new Error('Not a valid ethr DID: did:ethr:2nQtiQG6Cgm1GYTBaaKAgr76uY7iSexUkqX')
)
})
})
})
7 changes: 4 additions & 3 deletions src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { BigNumber } from '@ethersproject/bignumber'
import { Contract, ContractFactory } from '@ethersproject/contracts'
import { InfuraProvider, JsonRpcProvider, Provider } from '@ethersproject/providers'
import DidRegistryContract from 'ethr-did-registry'
import { DEFAULT_REGISTRY_ADDRESS, knownNetworks } from './helpers'
import { DEFAULT_REGISTRY_ADDRESS, knownInfuraNetworks, knownNetworks } from './helpers'

/**
* A configuration entry for an ethereum network
Expand Down Expand Up @@ -57,8 +57,9 @@ function getContractForNetwork(conf: ProviderConfiguration): Contract {
let provider: Provider = conf.provider || conf.web3?.currentProvider
if (!provider) {
if (conf.rpcUrl) {
const chainId = conf.chainId ? BigNumber.from(conf.chainId).toNumber() : conf.chainId
const networkName = knownNetworks[conf.name || ''] ? conf.name?.replace('mainnet', 'homestead') : 'any'
const chainIdRaw = conf.chainId ? conf.chainId : knownNetworks[conf.name || '']
const chainId = chainIdRaw ? BigNumber.from(chainIdRaw).toNumber() : chainIdRaw
const networkName = knownInfuraNetworks[conf.name || ''] ? conf.name?.replace('mainnet', 'homestead') : 'any'
provider = new JsonRpcProvider(conf.rpcUrl, chainId || networkName)
} else {
throw new Error(`invalid_config: No web3 provider could be determined for network ${conf.name || conf.chainId}`)
Expand Down
27 changes: 26 additions & 1 deletion src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export function interpretIdentifier(identifier: string): { address: string; publ
}
}

const knownInfuraNetworks: Record<string, string> = {
export const knownInfuraNetworks: Record<string, string> = {
mainnet: '0x1',
ropsten: '0x3',
rinkeby: '0x4',
Expand All @@ -108,4 +108,29 @@ const knownInfuraNetworks: Record<string, string> = {

export const knownNetworks: Record<string, string> = {
...knownInfuraNetworks,
rsk: '0x1e',
'rsk:testnet': '0x1f',
artis_t1: '0x03c401',
artis_s1: '0x03c301',
matic: '0x89',
maticmum: '0x13881',
}

export enum Errors {
/**
* The resolver has failed to construct the DID document.
* This can be caused by a network issue, a wrong registry address or malformed logs while parsing the registry history.
* Please inspect the `DIDResolutionMetadata.message` to debug further.
*/
notFound = 'notFound',

/**
* The resolver does not know how to resolve the given DID. Most likely it is not a `did:ethr`.
*/
invalidDid = 'invalidDid',

/**
* The resolver is misconfigured or is being asked to resolve a DID anchored on an unknown network
*/
unknownNetwork = 'unknownNetwork',
}
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
legacyAttrTypes,
stringToBytes32,
verificationMethodTypes,
Errors,
} from './helpers'

export {
Expand All @@ -20,4 +21,5 @@ export {
legacyAttrTypes as attrTypes,
verificationMethodTypes,
identifierMatcher,
Errors,
}
24 changes: 20 additions & 4 deletions src/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
nullAddress,
DIDOwnerChanged,
knownNetworks,
Errors,
} from './helpers'
import { logDecoder } from './logParser'

Expand Down Expand Up @@ -280,13 +281,28 @@ export class EthrDidResolver {
): Promise<DIDResolutionResult> {
const fullId = parsed.id.match(identifierMatcher)
if (!fullId) {
throw new Error(`Not a valid ethr DID: ${did}`)
return {
didResolutionMetadata: {
error: Errors.invalidDid,
message: `Not a valid did:ethr: ${parsed.id}`,
},
didDocumentMetadata: {},
didDocument: null,
}
}
const id = fullId[2]
const networkId = !fullId[1] ? 'mainnet' : fullId[1].slice(0, -1)

if (!this.contracts[networkId])
throw new Error(`unknown_network: The DID resolver does not have a configuration for network: ${networkId}`)
if (!this.contracts[networkId]) {
return {
didResolutionMetadata: {
error: Errors.unknownNetwork,
message: `The DID resolver does not have a configuration for network: ${networkId}`,
},
didDocumentMetadata: {},
didDocument: null,
}
}

const { controller, history, controllerKey, chainId } = await this.changeLog(id, networkId, options.blockTag)
try {
Expand All @@ -300,7 +316,7 @@ export class EthrDidResolver {
} catch (e) {
return {
didResolutionMetadata: {
error: 'notFound',
error: Errors.notFound,
message: e.toString(), // This is not in spec, nut may be helpful
},
didDocumentMetadata: {},
Expand Down

0 comments on commit 2a023b1

Please sign in to comment.