Git Product home page Git Product logo

did-veres-one's Introduction

Veres One

A blockchain for acquiring and managing decentralized identifiers.

The Veres One Project envisions a world where people and organizations control their identifiers and their identity data. The Veres One Blockchain is a fit-for-purpose blockchain optimized for identity on the Web. The network ecosystem is designed to be self-sufficient through the use of an innovative operational and funding model. The operational model ensures openness, prevents attacks against the network, and financially rewards individuals and organizations that choose to run software to ensure the security of the network.

Human dignity demands that every individual be able to participate equally in our increasingly digital society. That means everyone deserves the ability create and administer unique, globally resolvable identifiers. For that reason, the network is global and open to the public; anyone may participate.

You can learn more about this project at the Veres One Website.

Technical details about the blockchain can be found in the Veres One DID Method Specification.

Requirements

  • Linux (Debian 10+, Ubuntu 18.04+)
  • Node 12.11+
  • MongoDB (3.6+)
  • Redis (4+)

Evaluation Quickstart

You can create DIDs to the Veres One Testnet by using the did-client:

git clone https://github.com/digitalbazaar/did-cli.git
cd did-cli
npm install
./did generate --register

Developer Quickstart

Setting up a Veres One development environment is fairly easy and consists of the following steps:

  1. Modify your /etc/hosts file.
  2. Install Git, Node, MongoDB, and Redis.
  3. Setup the Veres One development environment.

Detailed instructions can be found below:

Make sure to add the following hostnames to your /etc/hosts file:

127.0.0.1  localhost node-1.veres.one.local node-2.veres.one.local \
           node-3.veres.one.local node-4.veres.one.local

The \ and line break above is for readability purposes. Every *.veres.one.local should be on the same line as 127.0.0.1.

git clone https://github.com/veres-one/veres-one.git
cd veres-one
npm install
node dev.js

You can write DIDs to the development blockchain by using the did-client:

git clone https://github.com/digitalbazaar/did-cli.git
cd did-cli
npm install
./did -m dev generate --register

If you want to run a minimum network with electors, you will have to run 4 nodes:

cd veres-one
node node-1 &
node node-2 &
node node-3 &
node node-4 &

When you create a DID, you should see all peers vote and synchronize to the same block.

Issue Tracker

All bugs, suggestions, requests, and code issues are tracked on the Veres One Issue Tracker.

did-veres-one's People

Contributors

aljones15 avatar davidlehn avatar dlongley avatar dmitrizagidulin avatar gannan08 avatar jsassassin avatar mattcollier avatar msporny avatar tplooker avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

did-veres-one's Issues

Fix jsdocs per new linting rules.

The jsdocs are non-conforming to the linting rules.

Need to enable eslint-config-digitalbazaar/jsdoc and clean-up all the errors.

Error adding service endpoint to DID

Playing around with VeresOne to try to create a DID for us to use, which will require some service endpoints. I've run into a client error sending the did document to the Veres one blockchain (using the interop one, which I've redacted from the snippets in case that was supposed to be private).

Error:

(node:12416) UnhandledPromiseRejectionWarning: NetworkError: Error sending document.
    at WebLedgerClient.sendDocument (/Users/anthony/Dev/Repos/did-test/node_modules/web-ledger-client/lib/WebLedgerClient.js:253:21)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async VeresOne.send (/Users/anthony/Dev/Repos/did-test/node_modules/did-veres-one/lib/VeresOne.js:243:22)
    at async VeresOne.register (/Users/anthony/Dev/Repos/did-test/node_modules/did-veres-one/lib/VeresOne.js:188:5)
    at async test (/Users/anthony/Dev/Repos/did-test/did-test-create-service.js:27:32)
(node:12416) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:12416) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Having a debugger on WebLedgerClient, the response error looks to be 400 | ValidationError | "The input is invalid"

The full request document looks to be like

{
  "@context": "https://w3id.org/webledger/v1",
  "creator": "https://REDACTED/consensus/continuity2017/voters/z6MktdvC8wTVN2Rkkqiivdc95eih5EJrcu8jC4uKh1FGvhvx",
  "type": "CreateWebLedgerRecord",
  "record": {
    "@context": [
      "https://w3id.org/did/v0.11",
      "https://w3id.org/veres-one/v1"
    ],
    "id": "did:v1:test:nym:z6MkiUBCV4WG4ciU5vPq2ExK6AUUT5KxU7BYH6wW5dsSBUY4",
    "authentication": [
      {
        "id": "did:v1:test:nym:z6MkiUBCV4WG4ciU5vPq2ExK6AUUT5KxU7BYH6wW5dsSBUY4#z6MkqDYLpFyjvBCjaFWhijniEGAsejEXpScyH65WDHPTVUEd",
        "type": "Ed25519VerificationKey2018",
        "controller": "did:v1:test:nym:z6MkiUBCV4WG4ciU5vPq2ExK6AUUT5KxU7BYH6wW5dsSBUY4",
        "publicKeyBase58": "BmHJE1jJadiGTkg13ApsPAcsq9xgQZNcb5AaP1RSaFTF"
      }
    ],
    "capabilityInvocation": [
      {
        "id": "did:v1:test:nym:z6MkiUBCV4WG4ciU5vPq2ExK6AUUT5KxU7BYH6wW5dsSBUY4#z6MkiUBCV4WG4ciU5vPq2ExK6AUUT5KxU7BYH6wW5dsSBUY4",
        "type": "Ed25519VerificationKey2018",
        "controller": "did:v1:test:nym:z6MkiUBCV4WG4ciU5vPq2ExK6AUUT5KxU7BYH6wW5dsSBUY4",
        "publicKeyBase58": "51v9tpFpj5DzyRZ8LfzUF4vUdW474DwBb62aFMuRGFkg"
      }
    ],
    "capabilityDelegation": [
      {
        "id": "did:v1:test:nym:z6MkiUBCV4WG4ciU5vPq2ExK6AUUT5KxU7BYH6wW5dsSBUY4#z6Mkh5CRC7VMKZvFniVk8LtwZnM4wouEkkkV3NY8pnvs7qzy",
        "type": "Ed25519VerificationKey2018",
        "controller": "did:v1:test:nym:z6MkiUBCV4WG4ciU5vPq2ExK6AUUT5KxU7BYH6wW5dsSBUY4",
        "publicKeyBase58": "3cwNbsEuz2RngDf3Smw6igo58EdPLsW8MMdCzWxrCdDb"
      }
    ],
    "assertionMethod": [
      {
        "id": "did:v1:test:nym:z6MkiUBCV4WG4ciU5vPq2ExK6AUUT5KxU7BYH6wW5dsSBUY4#z6Mkg2qKhmsPyN91Sp2SeyBhCHQwMGDFu3A7K8MyEM7oKub4",
        "type": "Ed25519VerificationKey2018",
        "controller": "did:v1:test:nym:z6MkiUBCV4WG4ciU5vPq2ExK6AUUT5KxU7BYH6wW5dsSBUY4",
        "publicKeyBase58": "2aaH7XcxdpeYLKBjyQDrMBrwXgwQV9ukd7T3Q59nQgog"
      }
    ],
    "service": [
      {
        "id": "did:v1:test:nym:z6MkiUBCV4WG4ciU5vPq2ExK6AUUT5KxU7BYH6wW5dsSBUY4#service1",
        "serviceEndpoint": "https://agent.example.com",
        "type": "urn:AgentService"
      }
    ]
  },
  "proof": [
    {
      "type": "Ed25519Signature2018",
      "created": "2020-03-05T17:01:03Z",
      "creator": "did:v1:test:nym:z279yHL6HsxRzCPU78DAWgZVieb8xPK1mJKJBbP8T2CezuFY#z279yHL6HsxRzCPU78DAWgZVieb8xPK1mJKJBbP8T2CezuFY",
      "capability": "did:v1:uuid:c37e914a-1e2a-4d59-9668-ee93458fd19a",
      "capabilityAction": "write",
      "jws": "MOCKPROOF",
      "proofPurpose": "capabilityInvocation"
    },
    {
      "type": "Ed25519Signature2018",
      "created": "2020-03-05T17:01:06Z",
      "verificationMethod": "did:v1:test:nym:z6MkiUBCV4WG4ciU5vPq2ExK6AUUT5KxU7BYH6wW5dsSBUY4#z6MkiUBCV4WG4ciU5vPq2ExK6AUUT5KxU7BYH6wW5dsSBUY4",
      "proofPurpose": "capabilityInvocation",
      "capability": "did:v1:test:nym:z6MkiUBCV4WG4ciU5vPq2ExK6AUUT5KxU7BYH6wW5dsSBUY4",
      "capabilityAction": "create",
      "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..5TcgiYsR0q92WCsCkUPMX5D6AZQH5-d_p3u6YMwAw7zypi8oQHrPGTnqzxMG_eJDVyHQN_o7ka5Fq853bgfDBw"
    }
  ]
}

This works fine without trying to add a service endpoint.

Reproduction code:

const v1 = require('did-veres-one');
const https = require('https');

const hostname = REDACTED;

async function test() {
    const httpsAgent = new https.Agent;

    const options = {mode: 'test', httpsAgent, hostname};
    const veresDriver = v1.driver(options);

    // Generate a new DID Document
    const didDocument = await veresDriver.generate({didType: 'nym', keyType: 'Ed25519VerificationKey2018'});

    // create service endpoint for did
    const serviceOptions = {
        fragment: "service1",
        endpoint: 'https://agent.example.com',
        type: 'urn:AgentService'
    };
    didDocument.addService(serviceOptions);

    // Log the new didDocument to the console.
    console.log('Generated:', JSON.stringify(didDocument, null, 2));

    const registrationResult = await veresDriver.register({didDocument});

    // Log the result of registering the didDoc to the VeresOne Test ledger
    console.log('Registered!', JSON.stringify(registrationResult, null, 2));
}

test();

I've also tried to register a simple DID first, then observe(), addService() and update() afterwards but it looked like a similar problem.

I didn't see much documentation on adding service endpoints, just looking through the code mostly. Is there something obvious that I did incorrectly?

As an aside, I noticed service type requires a uri. Is that specific to veres one? Didn't look like that was a requirement in the DID spec.

DRY Up Error handling for HTTPError

There are multiple places in this library where there are similar error handling statements:

} catch(e) {
const {response} = e;
// if there is no response just rethrow the error
if(!response) {
throw e;
}
const error = new VeresOneClientError(
'Error retrieving record.', 'NetworkError');
error.details = {
baseURL: ticketService, error: e, status: response.status, result
};
// errors in this range might contain response data
if(response.status > 399 && response.status < 500) {
// httpClient puts the data directly on the error
error.details.error = e.data || response.data || e;
}
throw error;
}

} catch(e) {
const {response} = e;
// this ensures we don't hide errors such as invalid URL
if(!response) {
throw e;
}
const error = new VeresOneClientError(
'Error retrieving record.', 'NetworkError');
error.details = {
baseURL: acceleratorUrl, error: e, status: response.status, result
};
// errors in this range might contain response data
if(response.status > 399 && response.status < 500) {
// httpClient puts the error on the data object
error.details.error = e.data || response.data || e;
}
throw error;
}

Create a helper function to handle them.

Add mock support for Ticket Service

Notes from chat.

Something like:

{
  type: 'GraphCycleProof2018', 
  powDifficulty: <base64Url-encoded blob>, 
  proofValue: <base64Url-encoded blob>
}

dlongley: powDifficulty is just an integer and proofValue is an array of integers and some other stuff
so... the client is going to contact a ticket service, get a ticket, do a PoW on it + their operation, send it to the ticket service and get their operation back with an ocap invocation proof on it .

after you get the operation back with the invocation proof on it, you follow the same code path as the accelerator version

TODO/FIXME Count 8

  • TODO: support methods that are not LDKeyPairs
    Commit: (73b11da) Change API names.
    File: lib/VeresOneDidDoc.js:450
    Matthew Collier commented a year ago

  • TODO: Check for revocation and expiration
    Commit: (5f79655) Implement doc.suiteKeyNode(), use updated crypto-ld. (#19)
    File: lib/VeresOneDidDoc.js:275
    Dmitri Zagidulin commented a year ago

  • TODO: update to use (expires) pseudo header or just use
    Commit: (b236096) Fix style.
    File: lib/VeresOneClient.js:214
    Matthew Collier commented 8 months ago

  • FIXME: the web-ledger-client 1.0 APIs need some refinement, possibly
    Commit: (f0d4fc0) Implement update operations.
    File: lib/VeresOneClient.js:203
    Matthew Collier commented a year ago

  • FIXME: currently unused, update this implementation after testnet v2
    Commit: (795de18) Use TypeError.
    File: lib/VeresOneClient.js:145
    Matthew Collier commented a year ago

  • FIXME - remove, replace with cache
    Commit: (aa51dcd) Add a forceConstruct override to get().
    File: lib/VeresOneClient.js:63
    Dmitri Zagidulin commented 2 months ago

  • TODO: support signer API as alternative to privateKeyPem
    Commit: (1ef270c) Extract VeresOne code from did-io.
    File: lib/veres-one.js:330
    Dmitri Zagidulin commented 2 years ago

  • FIXME: validate didDocument, creator, and privateKeyPem
    Commit: (1ef270c) Extract VeresOne code from did-io.
    File: lib/veres-one.js:329
    Dmitri Zagidulin commented 2 years ago

Can we add support for` Ed25519VerificationKey2018` key type?

Currently it looks like it only supports Ed25519VerificationKey2020 key pair types https://github.com/veres-one/did-veres-one/blob/v14.x/lib/VeresOneDriver.js#L716-L724. Can we make this also support Ed25519VerificationKey2018 key type?

I get the following error for this test https://github.com/digitalbazaar/bedrock-vc-verifier/blob/update-documentLoader/test/mocha/10-verify.js#L27 when I update config['did-io'].methods.v1.verificationSuite value to Ed25519VerificationKey2018 here https://github.com/digitalbazaar/bedrock-vc-verifier/blob/update-documentLoader/lib/config.js#L22

{
  name: 'VerificationError',
  errors: [
    {
      name: 'Error',
      message: 'Cannot derive key agreement key from verification key type "Ed25519VerificationKey2018".',
      stack: 'Error: Cannot derive key agreement key from verification key type "Ed25519VerificationKey2018".\n' +
        '    at _deriveKeyAgreementKey (/Users/tashid.gyeltshen/Desktop/DigitalBazaar/bedrock-vc-verifier/test/node_modules/bedrock-did-io/node_modules/did-veres-one/lib/VeresOneDriver.js:713:11)\n' +
        '    at Function.generate (/Users/tashid.gyeltshen/Desktop/DigitalBazaar/bedrock-vc-verifier/test/node_modules/bedrock-did-io/node_modules/did-veres-one/lib/VeresOneDriver.js:280:7)\n' +
        '    at fromNym (/Users/tashid.gyeltshen/Desktop/DigitalBazaar/bedrock-vc-verifier/test/node_modules/bedrock-did-io/node_modules/did-veres-one/lib/VeresOneDriver.js:691:25)\n' +
        '    at VeresOneDriver.get (/Users/tashid.gyeltshen/Desktop/DigitalBazaar/bedrock-vc-verifier/test/node_modules/bedrock-did-io/node_modules/did-veres-one/lib/VeresOneDriver.js:120:32)\n' +
        '    at processTicksAndRejections (internal/process/task_queues.js:93:5)\n' +
        '    at async LruCache.memoize (/Users/tashid.gyeltshen/Desktop/DigitalBazaar/bedrock-vc-verifier/test/node_modules/@digitalbazaar/lru-memoize/lib/LruCache.js:64:16)\n' +
        '    at async JsonLdDocumentLoader.documentLoader (/Users/tashid.gyeltshen/Desktop/DigitalBazaar/bedrock-vc-verifier/test/node_modules/jsonld-document-loader/lib/JsonLdDocumentLoader.js:63:20)\n' +
        '    at async Ed25519Signature2020.getVerificationMethod (/Users/tashid.gyeltshen/Desktop/DigitalBazaar/bedrock-vc-verifier/test/node_modules/bedrock-vc-verifier/node_modules/@digitalbazaar/ed25519-signature-2020/lib/Ed25519Signature2020.js:158:24)\n' +
        '    at async Ed25519Signature2020.verifyProof (/Users/tashid.gyeltshen/Desktop/DigitalBazaar/bedrock-vc-verifier/test/node_modules/bedrock-vc-verifier/node_modules/jsonld-signatures/lib/suites/LinkedDataSignature.js:176:34)\n' +
        '    at async /Users/tashid.gyeltshen/Desktop/DigitalBazaar/bedrock-vc-verifier/test/node_modules/bedrock-vc-verifier/node_modules/jsonld-signatures/lib/ProofSet.js:236:53'
    }
  ]
} 

Update dependencies

@digitalbazaar/ed25519-signature-2020, @digitalbazaar/http-client and @digitalbazaar/zcap should be updated to the latest versions.

Add helper method to fetch capabilityInvocation key from DID Doc

Context, @mattcollier and I were discussing "how do you get a capability invocation key instance from a DID Doc (so you can pass it to jsonld-signatures etc)", and currently we're doing it like this:

const invokeKeyData = this.doc.capabilityInvocation[0].publicKey[0];
const keyPair = await LDKeyPair.from(invokeKeyData);

And Matt said, "we need something better than that" (especially the array stuff), and I completely agree. Alternatives below, in comments.

Remove apisauce

Use @digitalbazaar/http-client wherever necessary as a replacement for apisauce and axios.

github actions and karma tests are broken

Seems to be related to the use of nock:

ERROR in ./node_modules/nock/lib/back.js 3:15-32
Module not found: Error: Can't resolve 'assert' in '/home/liminal18/Programs/nodejs/veres_one/did-veres-one/node_modules/nock/lib'

Branch: v14.x
Steps:

  1. npm i
  2. npm run test-karma

Related:

nock/nock#1471

Nock issue from 2019 suggests that nock doesn't work in the browser at all.

Related:
#58

Verification Suites

Here is a proposal related to simplifying proof types: digitalbazaar/jsonld-signatures#37 (comment)

Here is a sample DID document: https://gist.github.com/mattcollier/123bcd73881e9160cb522bca857be673#file-maintainerdiddoc-json-L21

The proposal is that the type found on L7,21,35 would all be the same value. And that value (for now) would be one of two: Ed25519SignatureVerification2018, RsaSignatureVerification2018

This type would indicate what sort of verification material should be expected in the suite document. Both of these types would include a publicKey property (as now) that includes keys of the proper corresponding types: Ed25519VerificationKey2018, RsaVerificationKey2018

We foresee that other types of verification may be desirable that provide different meta data. Such as fingerprint verification.

Have I summarized this properly?

If so, could we simplify further for the types found on L7,21,35 and use one unifying term CryptographicSignatureVerification2018? This would allow the suite document to contain public keys of multiple types. What we are trying to communicate with this type is that one should be looking for a publicKey property in the suite document which any asymmetric algorithm would have.

I am looking to get final agreement on this proposal so that we can start coding it up.

attachInvocationProof takes both a key and a signer

/**
* Adds a zcap-style invocation proof to an operation.
*
* @param {object} operation - WebLedger operation.
*
* @param {object} options - Options hashmap.
* @param {string} capability - Capability (DID) url.
* @param {string} capabilityAction - 'create' / 'update'.
*
* Either a key pair instance or a signer object (from a KMS) is required:
* @param {LDKeyPair} [options.key] - A capabilityInvocation
* public/private key pair instance.
* @param {{sign: Function, id: string}} [options.signer] - A signer-type object
* such as that provided by a KMS.
*
* @returns {Promise<object>}
*/
async function attachInvocationProof(operation, {
capability, capabilityAction, key, signer
} = {}) {
return jsigs.sign(operation, {
documentLoader,
suite: new Ed25519Signature2020({key, signer}),
purpose: new CapabilityInvocation({capability, capabilityAction})
});
}

Questions:

  1. Why do we need both a signer and a key?
  2. Can we just pass in one of them?

Answer:

  1. I believe we accommodate passing in either a key or signer. We might want to make sure you're only passing in one with a warning.

Extract storage related operations from VeresOne driver

(Working off of the fix-browser-support branch):

  • storage module and dependency already removed
  • Remove VeresOne.saveDoc() -- will be the responsibility of calling code to store the did doc
  • Remove VeresOne.saveKeys() -- will be the responsibility of calling code to save keys
  • Do not automatically call saveDoc and saveKeys when generating a new did doc
  • Do not automatically call saveDoc and saveKeys when updating a did doc

These two items I'm less sure about:

  • Currently distinguishes between getLocal() (local did store) and getRemote() (from ledger). Remove that distinction - client code will need to do the equivalent of getLocal().
  • When retrieving a DID Doc via get() (local or remote), the driver imports private keys (that correspond to the public keys in the doc) from a key store. This will need to be handled by client code.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.