Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature. Create Public DID from aca-py #150

Closed
SmithSamuelM opened this issue Aug 20, 2019 · 12 comments
Closed

Feature. Create Public DID from aca-py #150

SmithSamuelM opened this issue Aug 20, 2019 · 12 comments

Comments

@SmithSamuelM
Copy link

Currently in order to create schema and crew_defs on an Indy ledger the demos for the aca-py suggest using the von-network browser web interface for creating the public DID. A useful feature would be to provide this capability in the OpenAPI interface for aca-py. This makes the aca-py agent more self contained.

@rosenbrockc
Copy link
Contributor

I need this now and am happy to contribute it. I propose adding the following abstract method to aries_cloudagent/wallet/base.py and implementing it for indy:

@abstractmethod
    async def register_nym(self, did: str, verkey: str, role: str = None):
        """
       Register a nym on the ledger.

        Args:
            did: DID to register on the ledger.
            verkey: The verification key of the keypair.
            role: For permissioned ledgers, what role should the new DID have.
        """

I would expose it as an endpoint in the wallet section of the swagger. Also, at the same time I would like to expose the sign_message, verify_message methods of the wallet to the swagger.

On a slightly different topic, I also need to expose the ledger methods for get_key_for_did and get_endpoint_for_did. Since there isn't a messaging section for ledger yet, I would just create one following the pattern of the others.

As I said, I am going to do this anyway, but would prefer to contribute it meaningfully than just maintain a separate fork. Just looking for the okay that this proposal is good.

@swcurran
Copy link
Contributor

swcurran commented Sep 10, 2019

Awesome! I'll ping @andrewwhitehead and @nrempel to take a look at this idea and provide feedback. Love getting contributions from a broader community.

FYI @jljordan42

@rosenbrockc
Copy link
Contributor

On second thoughts, I think that register_nym belongs in the ledger section. That's where I'm putting it for now.

@andrewwhitehead
Copy link
Contributor

What is the use case for register_nym? Since only a steward can perform that action on the ledger it doesn't seem generally useful. I also wonder about exposing the other methods via the admin API versus adding more task-based functionality. If the controller asks for a message to be signed, how does that message then get delivered? If you're fetching the endpoint manually and delivering it from the controller, that seems redundant given the functionality of the agent.

@rosenbrockc
Copy link
Contributor

rosenbrockc commented Sep 10, 2019

At the moment, ACA won't start unless it can verify that it's DID is on the ledger. Thus, every agent needs to have someone register their DID/verkey for them independently before they can even start the agent. Generally, the only reason the ledger exists is to stake a point-in-time claim to a DID and register its endpoint.

Use case: suppose that we want our users to have their own cloud agents and registered DIDs. And the process should be automated. We could run a separate web server endpoint that calls Indy-SDK directly to allow registration (via API key) of those agents to the ledger on startup to improve the UX for our customers. But then we are duplicating functionality that already exists in ACA. I think it is better to deploy a custom controller for the corporate endpoint that allows customers to register DIDs from their agents. That controller would (internally) call the ACA endpoint to register a NYM for the individual. Then, later, when the product is whitelabeled/resold, others can deploy their corporate controllers backed by the same ACA.

The main reason is that it seemed wasteful for me to call Indy-SDK in separate python code and go to the trouble of setting up ledger pools, wallets, etc. from the corporate side.

Another point is that ACA is eventually intended to be blockchain agnostic. It is possible that someone would deploy their own Indy/other ledger where there are many TRUST_ANCHOR-equivalent DIDs that can each register more users.

The use case for sign/verify functionality is with provenance chains. We could build that into ACA directly, but the exact format of the JSON object will be different depending on the use case. But, for example, we could require:

{
  "...": "...",
  "did": "did:method:...",
  "priors": [{"did": "did:sov:...", "signature": "..."},{"did": "did:other:...", "signature": "..."}],
  "signature": "..."
}

Then a single method could be exposed that verifies provenance for the entire packet. First, it checks the highest-level signature against the verkey for the did in the main attribute list. Then it looks through the priors and verifies each of those in turn.

There will likely be many other use cases for lower-level access to signatures and verifications. It is a trade-off as to whether they should be implemented in ACA or by the specific application that is using them.

Since the private keys for signing things are stored in the wallet in ACA, there isn't really a good way to support custom signature-based stuff without exposing these methods.

@swcurran
Copy link
Contributor

FYI - An ACA-Py agent does not have to have a DID on the ledger. In the Alice-Faber example, Alice does not have a public DID.

@rosenbrockc
Copy link
Contributor

In my development, when I don't register the DID on the ledger, I get an unhandled exception here: https://github.com/hyperledger/aries-cloudagent-python/blob/master/aries_cloudagent/config/ledger.py#L92

Which usually looks something like this:

ERROR: File "/home/indy/aries-cloudagent-python/aries_cloudagent/commands/start.py", line 66, in init
ERROR: await startup
ERROR: File "/home/indy/aries-cloudagent-python/aries_cloudagent/commands/start.py", line 22, in start_app
ERROR: await conductor.start()
ERROR: File "/home/indy/aries-cloudagent-python/aries_cloudagent/conductor.py", line 148, in start
ERROR: await ledger_config(context, public_did)
ERROR: File "/home/indy/aries-cloudagent-python/aries_cloudagent/config/ledger.py", line 92, in ledger_config
ERROR: await ledger.update_endpoint_for_did(public_did, endpoint)
ERROR: File "/home/indy/aries-cloudagent-python/aries_cloudagent/ledger/indy.py", line 555, in update_endpoint_for_did
ERROR: await self._submit(request_json, True, True)
ERROR: File "/home/indy/aries-cloudagent-python/aries_cloudagent/ledger/indy.py", line 253, in _submit
ERROR: f"Ledger rejected transaction request: {request_result['reason']}"
ERROR: aries_cloudagent.ledger.error.LedgerTransactionError: Ledger rejected transaction request: client request invalid: CouldNotAuthenticate('Can not find verkey for 3sxEoVWCRKCy4S4cqoVsSZ',)

@swcurran
Copy link
Contributor

@andrewwhitehead - your comment about not exposing other methods vs. task-based functionality is confusing to me. If the agent interfaces with the ledger, but the controller is the one that knows what the applications requirements are, how else are we to control the agent to take actions other than to use the admin API. For example, to revoke a credential, there is not an exchange required between the issuer and holder - just the issuer acting unilaterally. In that case, I would expect the controller to use the admin interface to trigger the revocation calls.

Am I missing something? And if that use case is OK, why not the controller telling the agent to create a DID (assuming it knows how--which I agree is tricky with authors and endorsers...).

@swcurran
Copy link
Contributor

In my development, when I don't register the DID on the ledger, I get an unhandled exception here: https://github.com/hyperledger/aries-cloudagent-python/blob/master/aries_cloudagent/config/ledger.py#L92

Which usually looks something like this:

ERROR: File "/home/indy/aries-cloudagent-python/aries_cloudagent/commands/start.py", line 66, in init
ERROR: await startup
ERROR: File "/home/indy/aries-cloudagent-python/aries_cloudagent/commands/start.py", line 22, in start_app
ERROR: await conductor.start()
ERROR: File "/home/indy/aries-cloudagent-python/aries_cloudagent/conductor.py", line 148, in start
ERROR: await ledger_config(context, public_did)
ERROR: File "/home/indy/aries-cloudagent-python/aries_cloudagent/config/ledger.py", line 92, in ledger_config
ERROR: await ledger.update_endpoint_for_did(public_did, endpoint)
ERROR: File "/home/indy/aries-cloudagent-python/aries_cloudagent/ledger/indy.py", line 555, in update_endpoint_for_did
ERROR: await self._submit(request_json, True, True)
ERROR: File "/home/indy/aries-cloudagent-python/aries_cloudagent/ledger/indy.py", line 253, in _submit
ERROR: f"Ledger rejected transaction request: {request_result['reason']}"
ERROR: aries_cloudagent.ledger.error.LedgerTransactionError: Ledger rejected transaction request: client request invalid: CouldNotAuthenticate('Can not find verkey for 3sxEoVWCRKCy4S4cqoVsSZ',)

What startup parameters are you using? Perhaps the --seed parameter? We think that is the issue with the start up.

@rosenbrockc
Copy link
Contributor

Yes, I am using the seed parameter. Though, in thinking about it further, I think I was initially able to do lots of things without setting the seeded DID to be public. I was experimenting with the OpenAPI and two agents a while back. Then, I needed a public DID to do something, so I set it using the OpenAPI endpoint.

I would recommend adding a check into the /wallet/did/public POST endpoint that first checks to see if the DID specified exists on the ledger (get_nym); if it doesn't, it won't allow the DID to be set public. Otherwise, you end up with a condition where the agent won't start unless the DID is registered (because of endpoint updates), but you can't unset it because the agent won't start (and the database is encrypted).

Sorry for this side-topic in this thread...

On the main thread topic, I coded up the ledger endpoint yesterday with unit tests. I'll submit a pull request and we can continue the discussion from there.

@HarshMultani
Copy link
Contributor

Hi @rosenbrockc where you able to solve that issue?
I am running the agent using the command :

aca-py start --wallet-name Steward --wallet-key Steward --wallet-type indy --genesis-file /<PATH_TO_GENESIS_FILE>/docker_pool_transactions_genesis --ledger-pool-name local_pool --inbound-transport http 127.0.0.1 8001 --admin 127.0.0.1 9001 --endpoint http://127.0.0.1:8001 --outbound-transport http --log-level DEBUG --admin-insecure-mode --seed 00000000000000000000000000000001

But then getting the same error :-

aries_cloudagent.config.base.ConfigError: Ledger rejected transaction request: client request invalid: could not authenticate, verkey for 4cLztgZYocjqTdAZM93t27 cannot be found

What am I doing wrong?

@ianco
Copy link
Contributor

ianco commented Oct 16, 2020

You need to create the DID on the ledger before you run aca-py.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants