diff --git a/CHANGELOG.md b/CHANGELOG.md index 291b594b46..3e90d82bd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,38 +1,72 @@ -# 1.0.0-rc0 +# 1.0.0-rc1 -## August 18, 2022 +## November 6, 2022 1.0.0 is a breaking update to ACA-Py whose version is intended to indicate the maturity of the implementation. The final 1.0.0 release will be Aries Interop -Profile 2.0-complete, and based on Python 3.7 or higher. The initial (rc0) -release candidate is for early adopters to provide feedback. +Profile 2.0-complete, and based on Python 3.7 or higher. ### Breaking Changes -As of rc0, there are no breaking updates in the release from the previous v0.7.4. -However, we know that there are some pending updates that will be breaking, hence -the bumps to the major/minor version elements. +As of release candidate 1.0.0-rc1, the only identified breaking change is the +handling of "unrevealed attributes" during verification (see +[\#1913](https://github.com/hyperledger/aries-cloudagent-python/pull/1913) for +details). As few implementations of Aries Wallets support unrevealed attributes +in an AnonCreds presentation, this is unlikely to impact any deployments. ### Categorized List of Pull Requests -In rc0, there are not a lot of new features, as the focus is on cleanup and +In rc1, there are not a lot of new features, as the focus is on cleanup and optimization. The biggest is the inclusion with ACA-Py of a universal resolver interface, allowing an instance to have both local resolvers for some DID Methods and a call out to an external universal resolver for other DID Methods. -While some work has been done on moving the default Python version beyond 3.6, -more work is still to be done on that before the final v1.0.0 release. +Another significant feature is full support for Hyperledger Indy transaction +endorsement for Authors and Endorsers. A new repo +[aries-endorser-service](https://github.com/hyperledger/aries-endorser-service) +has been created that is a pre-configured instance of ACA-Py for use as an +Endorser service. While some work has been done on moving the default Python +version beyond 3.6, more work is still to be done on that before the final +v1.0.0 release. ### Categorized List of Pull Requests -- Verifiable credential and revocation handling updates +- Verifiable credential, presentation and revocation handling updates - Refactor ledger correction code and insert into revocation error handling [\#1892](https://github.com/hyperledger/aries-cloudagent-python/pull/1892) ([ianco](https://github.com/ianco)) - Indy ledger fixes and cleanups [\#1870](https://github.com/hyperledger/aries-cloudagent-python/pull/1870) ([andrewwhitehead](https://github.com/andrewwhitehead)) - Refactoring of revocation registry creation [\#1813](https://github.com/hyperledger/aries-cloudagent-python/pull/1813) ([andrewwhitehead](https://github.com/andrewwhitehead)) + - Fix: the type of tails file path to string. [\#1925](https://github.com/hyperledger/aries-cloudagent-python/pull/1925) ([baegjae](https://github.com/baegjae)) + - Pre-populate revoc\_reg\_id on IssuerRevRegRecord [\#1924](https://github.com/hyperledger/aries-cloudagent-python/pull/1924) ([andrewwhitehead](https://github.com/andrewwhitehead)) + - Leave credentialStatus element in the LD credential [\#1921](https://github.com/hyperledger/aries-cloudagent-python/pull/1921) ([tsabolov](https://github.com/tsabolov)) + - **BREAKING:** Remove aca-py check for unrevealed revealed attrs on proof validation [\#1913](https://github.com/hyperledger/aries-cloudagent-python/pull/1913) ([ianco](https://github.com/ianco)) + - Send webhooks upon record/credential deletion [\#1906](https://github.com/hyperledger/aries-cloudagent-python/pull/1906) ([frostyfrog](https://github.com/frostyfrog)) + +- Out of Band (OOB) and DID Exchange / Connection Handling + - Fix: `--mediator-invitation` with OOB invitation + cleanup [\#1970](https://github.com/hyperledger/aries-cloudagent-python/pull/1970) ([shaangill025](https://github.com/shaangill025)) + - include image\_url in oob invitation [\#1966](https://github.com/hyperledger/aries-cloudagent-python/pull/1966) ([Zzocker](https://github.com/Zzocker)) + - feat: 00B v1.1 support [\#1962](https://github.com/hyperledger/aries-cloudagent-python/pull/1962) ([shaangill025](https://github.com/shaangill025)) + - Fix: OOB - Handling of minor versions [\#1940](https://github.com/hyperledger/aries-cloudagent-python/pull/1940) ([shaangill025](https://github.com/shaangill025)) + - fix: failed connectionless proof request on some case [\#1933](https://github.com/hyperledger/aries-cloudagent-python/pull/1933) ([kukgini](https://github.com/kukgini)) + - fix: propagate endpoint from mediation record [\#1922](https://github.com/hyperledger/aries-cloudagent-python/pull/1922) ([cjhowland](https://github.com/cjhowland)) + - Feat/public did endpoints for agents behind mediators [\#1899](https://github.com/hyperledger/aries-cloudagent-python/pull/1899) ([cjhowland](https://github.com/cjhowland)) - DID Registration and Resolution related updates - feat: add universal resolver [\#1866](https://github.com/hyperledger/aries-cloudagent-python/pull/1866) ([dbluhm](https://github.com/dbluhm)) - fix: resolve dids following new endpoint rules [\#1863](https://github.com/hyperledger/aries-cloudagent-python/pull/1863) ([dbluhm](https://github.com/dbluhm)) - fix: didx request cannot be accepted [\#1881](https://github.com/hyperledger/aries-cloudagent-python/pull/1881) ([rmnre](https://github.com/rmnre)) + - did method & key type registry [\#1986](https://github.com/hyperledger/aries-cloudagent-python/pull/1986) ([burdettadam](https://github.com/burdettadam)) + - Fix/endpoint attrib structure [\#1934](https://github.com/hyperledger/aries-cloudagent-python/pull/1934) ([cjhowland](https://github.com/cjhowland)) + - Simple did registry [\#1920](https://github.com/hyperledger/aries-cloudagent-python/pull/1920) ([burdettadam](https://github.com/burdettadam)) + - Use did:key for recipient keys [\#1886](https://github.com/hyperledger/aries-cloudagent-python/pull/1886) ([frostyfrog](https://github.com/frostyfrog)) + +- Hyperledger Indy Endorser/Author Transaction Handling + - Fix/txn job setting [\#1994](https://github.com/hyperledger/aries-cloudagent-python/pull/1994) ([ianco](https://github.com/ianco)) + - chore: fix ACAPY\_PROMOTE-AUTHOR-DID flag [\#1978](https://github.com/hyperledger/aries-cloudagent-python/pull/1978) ([morrieinmaas](https://github.com/morrieinmaas)) + + - Endorser write DID transaction [\#1938](https://github.com/hyperledger/aries-cloudagent-python/pull/1938) ([ianco](https://github.com/ianco)) + - Endorser doc updates and some bug fixes [\#1926](https://github.com/hyperledger/aries-cloudagent-python/pull/1926) ([ianco](https://github.com/ianco)) + +- Startup Command Line / Environment / YAML Parameter Updates + - Add seed command line parameter but use only if also an "allow insecure seed" parameter is set [\#1714](https://github.com/hyperledger/aries-cloudagent-python/pull/1714) ([DaevMithran](https://github.com/DaevMithran)) - Internal Aries framework data handling updates - fix: update RouteManager methods use to pass profile as parameter [\#1902](https://github.com/hyperledger/aries-cloudagent-python/pull/1902) ([chumbert](https://github.com/chumbert)) @@ -41,14 +75,35 @@ more work is still to be done on that before the final v1.0.0 release. - Enable manually triggering keylist updates during connection [\#1851](https://github.com/hyperledger/aries-cloudagent-python/pull/1851) ([dbluhm](https://github.com/dbluhm)) - feat: make base wallet route access configurable [\#1836](https://github.com/hyperledger/aries-cloudagent-python/pull/1836) ([dbluhm](https://github.com/dbluhm)) - feat: event and webhook on keylist update stored [\#1769](https://github.com/hyperledger/aries-cloudagent-python/pull/1769) ([dbluhm](https://github.com/dbluhm)) + - fix: Safely shutdown when root\_profile uninitialized [\#1960](https://github.com/hyperledger/aries-cloudagent-python/pull/1960) ([frostyfrog](https://github.com/frostyfrog)) + - feat: include connection ids in keylist update webhook [\#1914](https://github.com/hyperledger/aries-cloudagent-python/pull/1914) ([dbluhm](https://github.com/dbluhm)) + - fix: incorrect response schema for discover features [\#1912](https://github.com/hyperledger/aries-cloudagent-python/pull/1912) ([dbluhm](https://github.com/dbluhm)) + - Fix: SchemasInputDescriptorFilter: broken deserialization renders generated clients unusable [\#1894](https://github.com/hyperledger/aries-cloudagent-python/pull/1894) ([rmnre](https://github.com/rmnre)) + - fix: schema class can set Meta.unknown [\#1885](https://github.com/hyperledger/aries-cloudagent-python/pull/1885) ([dbluhm](https://github.com/dbluhm)) - Unit, Integration and Aries Agent Test Harness Test updates - Fixes a few AATH failures [\#1897](https://github.com/hyperledger/aries-cloudagent-python/pull/1897) ([ianco](https://github.com/ianco)) - fix: warnings in tests from IndySdkProfile [\#1865](https://github.com/hyperledger/aries-cloudagent-python/pull/1865) ([dbluhm](https://github.com/dbluhm)) - Unit test fixes for python 3.9 [\#1858](https://github.com/hyperledger/aries-cloudagent-python/pull/1858) ([andrewwhitehead](https://github.com/andrewwhitehead)) + - Update pip-audit.yml [\#1945](https://github.com/hyperledger/aries-cloudagent-python/pull/1945) ([ryjones](https://github.com/ryjones)) + - Update pip-audit.yml [\#1944](https://github.com/hyperledger/aries-cloudagent-python/pull/1944) ([ryjones](https://github.com/ryjones)) + +- Dependency Updates + - feat: update pynacl version from 1.4.0 to 1.50 [\#1981](https://github.com/hyperledger/aries-cloudagent-python/pull/1981) ([morrieinmaas](https://github.com/morrieinmaas)) + - Fix: web.py dependency - integration tests & demos [\#1973](https://github.com/hyperledger/aries-cloudagent-python/pull/1973) ([shaangill025](https://github.com/shaangill025)) + - chore: update pydid [\#1915](https://github.com/hyperledger/aries-cloudagent-python/pull/1915) ([dbluhm](https://github.com/dbluhm)) + +- Demo and Documentation Updates + - Fixes to acme exercise code [\#1990](https://github.com/hyperledger/aries-cloudagent-python/pull/1990) ([ianco](https://github.com/ianco)) + - Fixed bug in run\_demo script [\#1982](https://github.com/hyperledger/aries-cloudagent-python/pull/1982) ([pasquale95](https://github.com/pasquale95)) + - Transaction Author with Endorser demo [\#1975](https://github.com/hyperledger/aries-cloudagent-python/pull/1975) ([ianco](https://github.com/ianco)) + - Redis Plugins \[redis\_cache & redis\_queue\] related updates [\#1937](https://github.com/hyperledger/aries-cloudagent-python/pull/1937) ([shaangill025](https://github.com/shaangill025)) - Release management pull requests - Release 1.0.0-rc0 [\#1904](https://github.com/hyperledger/aries-cloudagent-python/pull/1904) ([swcurran](https://github.com/swcurran)) + - Add 0.7.5 patch Changelog entry to main branch Changelog [\#1996](https://github.com/hyperledger/aries-cloudagent-python/pull/1996) ([swcurran](https://github.com/swcurran)) + - Release 1.0.0-rc1 [\#2005](https://github.com/hyperledger/aries-cloudagent-python/pull/2005) ([swcurran](https://github.com/swcurran)) + # 0.7.5 diff --git a/aries_cloudagent/admin/server.py b/aries_cloudagent/admin/server.py index 6d84de327d..c7ab79334d 100644 --- a/aries_cloudagent/admin/server.py +++ b/aries_cloudagent/admin/server.py @@ -370,6 +370,7 @@ async def check_multitenant_authorization(request: web.Request, handler): and not is_server_path and not is_unprotected_path(path) and not base_limited_access_path + and not (request.method == "OPTIONS") # CORS fix ): raise web.HTTPUnauthorized() diff --git a/aries_cloudagent/config/argparse.py b/aries_cloudagent/config/argparse.py index 6822f72c2f..d19bff39c6 100644 --- a/aries_cloudagent/config/argparse.py +++ b/aries_cloudagent/config/argparse.py @@ -74,7 +74,8 @@ def create_argument_parser(*, prog: str = None): def load_argument_groups(parser: ArgumentParser, *groups: Type[ArgumentGroup]): - """Log a set of argument groups into a parser. + """ + Log a set of argument groups into a parser. Returns: A callable to convert loaded arguments into a settings dictionary @@ -872,32 +873,56 @@ def get_settings(self, args: Namespace) -> dict: if args.no_ledger: settings["ledger.disabled"] = True else: - configured = False + single_configured = False + multi_configured = False + update_pool_name = False if args.genesis_url: settings["ledger.genesis_url"] = args.genesis_url - configured = True + single_configured = True elif args.genesis_file: settings["ledger.genesis_file"] = args.genesis_file - configured = True + single_configured = True elif args.genesis_transactions: settings["ledger.genesis_transactions"] = args.genesis_transactions - configured = True + single_configured = True if args.genesis_transactions_list: with open(args.genesis_transactions_list, "r") as stream: txn_config_list = yaml.safe_load(stream) ledger_config_list = [] for txn_config in txn_config_list: ledger_config_list.append(txn_config) + if "is_write" in txn_config and txn_config["is_write"]: + if "genesis_url" in txn_config: + settings["ledger.genesis_url"] = txn_config[ + "genesis_url" + ] + elif "genesis_file" in txn_config: + settings["ledger.genesis_file"] = txn_config[ + "genesis_file" + ] + elif "genesis_transactions" in txn_config: + settings["ledger.genesis_transactions"] = txn_config[ + "genesis_transactions" + ] + else: + raise ArgsParseError( + "No genesis information provided for write ledger" + ) + if "id" in txn_config: + settings["ledger.pool_name"] = txn_config["id"] + update_pool_name = True settings["ledger.ledger_config_list"] = ledger_config_list - configured = True - if not configured: + multi_configured = True + if not (single_configured or multi_configured): raise ArgsParseError( "One of --genesis-url --genesis-file, --genesis-transactions " "or --genesis-transactions-list must be specified (unless " "--no-ledger is specified to explicitly configure aca-py to" " run with no ledger)." ) - if args.ledger_pool_name: + if single_configured and multi_configured: + raise ArgsParseError("Cannot configure both single- and multi-ledger.") + if args.ledger_pool_name and not update_pool_name: settings["ledger.pool_name"] = args.ledger_pool_name if args.ledger_keepalive: settings["ledger.keepalive"] = args.ledger_keepalive diff --git a/aries_cloudagent/core/conductor.py b/aries_cloudagent/core/conductor.py index c24862a4e9..9dfe8f8ab2 100644 --- a/aries_cloudagent/core/conductor.py +++ b/aries_cloudagent/core/conductor.py @@ -28,7 +28,7 @@ from ..config.wallet import wallet_config from ..core.profile import Profile from ..indy.verifier import IndyVerifier -from ..ledger.base import BaseLedger + from ..ledger.error import LedgerConfigError, LedgerTransactionError from ..ledger.multiple_ledger.base_manager import ( BaseMultipleLedgerManager, @@ -144,7 +144,6 @@ async def setup(self): self.root_profile.BACKEND_NAME == "askar" and ledger.BACKEND_NAME == "indy-vdr" ): - context.injector.bind_instance(BaseLedger, ledger) context.injector.bind_provider( IndyVerifier, ClassProvider( @@ -156,7 +155,6 @@ async def setup(self): self.root_profile.BACKEND_NAME == "indy" and ledger.BACKEND_NAME == "indy" ): - context.injector.bind_instance(BaseLedger, ledger) context.injector.bind_provider( IndyVerifier, ClassProvider( diff --git a/aries_cloudagent/indy/models/cred_request.py b/aries_cloudagent/indy/models/cred_request.py index 5a022bebc0..92a80e14d6 100644 --- a/aries_cloudagent/indy/models/cred_request.py +++ b/aries_cloudagent/indy/models/cred_request.py @@ -44,7 +44,7 @@ class Meta: unknown = EXCLUDE prover_did = fields.Str( - requred=True, + required=True, description="Prover DID", **INDY_DID, ) diff --git a/aries_cloudagent/protocols/routing/v1_0/manager.py b/aries_cloudagent/protocols/routing/v1_0/manager.py index 44c1b7b7c6..d200a30b59 100644 --- a/aries_cloudagent/protocols/routing/v1_0/manager.py +++ b/aries_cloudagent/protocols/routing/v1_0/manager.py @@ -1,5 +1,7 @@ """Routing manager classes for tracking and inspecting routing records.""" +import asyncio +import logging from typing import Coroutine, Sequence from ....core.error import BaseError @@ -16,6 +18,12 @@ from .models.route_updated import RouteUpdated +LOGGER = logging.getLogger(__name__) + +RECIP_ROUTE_PAUSE = 0.1 +RECIP_ROUTE_RETRY = 10 + + class RoutingManagerError(BaseError): """Generic routing error.""" @@ -54,21 +62,30 @@ async def get_recipient(self, recip_verkey: str) -> RouteRecord: if not recip_verkey: raise RoutingManagerError("Must pass non-empty recip_verkey") - try: - async with self._profile.session() as session: - record = await RouteRecord.retrieve_by_recipient_key( - session, recip_verkey + i = 0 + record = None + while not record: + try: + LOGGER.info(">>> fetching routing record for verkey: " + recip_verkey) + async with self._profile.session() as session: + record = await RouteRecord.retrieve_by_recipient_key( + session, recip_verkey + ) + LOGGER.info(">>> FOUND routing record for verkey: " + recip_verkey) + return record + except StorageDuplicateError: + LOGGER.info(">>> DUPLICATE routing record for verkey: " + recip_verkey) + raise RouteNotFoundError( + f"More than one route record found with recipient key: {recip_verkey}" ) - except StorageDuplicateError: - raise RouteNotFoundError( - f"More than one route record found with recipient key: {recip_verkey}" - ) - except StorageNotFoundError: - raise RouteNotFoundError( - f"No route found with recipient key: {recip_verkey}" - ) - - return record + except StorageNotFoundError: + LOGGER.info(">>> NOT FOUND routing record for verkey: " + recip_verkey) + i += 1 + if i > RECIP_ROUTE_RETRY: + raise RouteNotFoundError( + f"No route found with recipient key: {recip_verkey}" + ) + await asyncio.sleep(RECIP_ROUTE_PAUSE) async def get_routes( self, client_connection_id: str = None, tag_filter: dict = None @@ -136,6 +153,7 @@ async def create_route_record( ) if not recipient_key: raise RoutingManagerError("Missing recipient_key") + LOGGER.info(">>> creating routing record for verkey: " + recipient_key) route = RouteRecord( connection_id=client_connection_id, wallet_id=internal_wallet_id, @@ -143,6 +161,7 @@ async def create_route_record( ) async with self._profile.session() as session: await route.save(session, reason="Created new route") + LOGGER.info(">>> CREATED routing record for verkey: " + recipient_key) return route async def update_routes( diff --git a/aries_cloudagent/transport/inbound/http.py b/aries_cloudagent/transport/inbound/http.py index 8179023379..696cab4bd3 100644 --- a/aries_cloudagent/transport/inbound/http.py +++ b/aries_cloudagent/transport/inbound/http.py @@ -96,7 +96,12 @@ async def inbound_message_handler(self, request: web.BaseRequest): raise web.HTTPBadRequest() if inbound.receipt.direct_response_requested: - response = await session.wait_response() + # Wait for the message to be processed. Only send a response if a response + # buffer is present. + await inbound.wait_processing_complete() + response = ( + await session.wait_response() if session.response_buffer else None + ) # no more responses session.can_respond = False diff --git a/aries_cloudagent/transport/inbound/manager.py b/aries_cloudagent/transport/inbound/manager.py index 65d081454d..909703e7c5 100644 --- a/aries_cloudagent/transport/inbound/manager.py +++ b/aries_cloudagent/transport/inbound/manager.py @@ -181,6 +181,8 @@ def dispatch_complete(self, message: InboundMessage, completed: CompletedTask): if session and session.accept_undelivered and not session.response_buffered: self.process_undelivered(session) + message.dispatch_processing_complete() + def closed_session(self, session: InboundSession): """ Clean up a closed session. diff --git a/aries_cloudagent/transport/inbound/message.py b/aries_cloudagent/transport/inbound/message.py index 169b2dc35c..2def0e1d92 100644 --- a/aries_cloudagent/transport/inbound/message.py +++ b/aries_cloudagent/transport/inbound/message.py @@ -1,5 +1,6 @@ """Classes representing inbound messages.""" +import asyncio from typing import Union from .receipt import MessageReceipt @@ -23,3 +24,12 @@ def __init__( self.receipt = receipt self.session_id = session_id self.transport_type = transport_type + self.processing_complete_event = asyncio.Event() + + def dispatch_processing_complete(self): + """Dispatch processing complete.""" + self.processing_complete_event.set() + + async def wait_processing_complete(self): + """Wait for processing to complete.""" + await self.processing_complete_event.wait() diff --git a/aries_cloudagent/transport/inbound/tests/test_http_transport.py b/aries_cloudagent/transport/inbound/tests/test_http_transport.py index c440fe7a57..fd74775572 100644 --- a/aries_cloudagent/transport/inbound/tests/test_http_transport.py +++ b/aries_cloudagent/transport/inbound/tests/test_http_transport.py @@ -62,6 +62,7 @@ def receive_message( message: InboundMessage, can_respond: bool = False, ): + message.wait_processing_complete = async_mock.CoroutineMock() self.message_results.append((message.payload, message.receipt, can_respond)) if self.result_event: self.result_event.set() @@ -119,13 +120,15 @@ async def test_send_message_outliers(self): mock_session.return_value = async_mock.MagicMock( receive=async_mock.CoroutineMock( return_value=async_mock.MagicMock( - receipt=async_mock.MagicMock(direct_response_requested=True) + receipt=async_mock.MagicMock(direct_response_requested=True), + wait_processing_complete=async_mock.CoroutineMock(), ) ), can_respond=True, profile=InMemoryProfile.test_profile(), clear_response=async_mock.MagicMock(), wait_response=async_mock.CoroutineMock(return_value=b"Hello world"), + response_buffer="something", ) async with self.client.post("/", data=test_message) as resp: result = await resp.text() diff --git a/aries_cloudagent/transport/inbound/tests/test_message.py b/aries_cloudagent/transport/inbound/tests/test_message.py new file mode 100644 index 0000000000..71a8defee8 --- /dev/null +++ b/aries_cloudagent/transport/inbound/tests/test_message.py @@ -0,0 +1,30 @@ +import asyncio + +from asynctest import TestCase + +from ..message import InboundMessage +from ..receipt import MessageReceipt + + +class TestInboundMessage(TestCase): + async def test_wait_response(self): + message = InboundMessage( + payload="test", + connection_id="conn_id", + receipt=MessageReceipt(), + session_id="session_id", + ) + assert not message.processing_complete_event.is_set() + message.dispatch_processing_complete() + assert message.processing_complete_event.is_set() + + message = InboundMessage( + payload="test", + connection_id="conn_id", + receipt=MessageReceipt(), + session_id="session_id", + ) + assert not message.processing_complete_event.is_set() + task = message.wait_processing_complete() + message.dispatch_processing_complete() + await asyncio.wait_for(task, 1) diff --git a/aries_cloudagent/version.py b/aries_cloudagent/version.py index dd12aefad4..7e5ca62006 100644 --- a/aries_cloudagent/version.py +++ b/aries_cloudagent/version.py @@ -1,4 +1,4 @@ """Library version information.""" -__version__ = "1.0.0-rc0" +__version__ = "1.0.0-rc1" RECORD_TYPE_ACAPY_VERSION = "acapy_version" diff --git a/demo/AliceWantsAJsonCredential.md b/demo/AliceWantsAJsonCredential.md index 8f37bbbc47..82c83844da 100644 --- a/demo/AliceWantsAJsonCredential.md +++ b/demo/AliceWantsAJsonCredential.md @@ -29,10 +29,14 @@ Open up a second shell (so you have 2 shells open in the `demo` directory) and i Note that you start the `faber` agent with AIP2.0 options. (When you specify `--cred-type json-ld` faber will set aip to `20` automatically, so the `--aip` option is not strictly required.) +Also note that the above will only work with the `/issue-credential-2.0/create-offer` endpoint. If you want to use the `/issue-credential-2.0/send` endpoint - which automates each step of the credential exchange - you will need to include the `--no-auto` option when starting each of the alice and faber agents (since the alice and faber controllers *also* automatically respond to each step in the credential exchange). + (Alternately you can run run Alice and Faber agents locally, see the `./faber-local.sh` and `./alice-local.sh` scripts in the `demo` directory.) Copy the "invitation" json text from the Faber shell and paste into the Alice shell to establish a connection between the two agents. +(If you are running with `--no-auto` you will also need to call the `/connections/accept-invitation` endpoint in alice's admin api swagger page.) + Now open up two browser windows to the [Faber](http://localhost:8021/api/doc) and [Alice](http://localhost:8031/api/doc) admin api swagger pages. Using the Faber admin api, you have to create a DID with the appropriate: @@ -78,7 +82,9 @@ Congradulations, you are now ready to start issuing JSON-LD credentials! - You have created a (non-public) DID for Faber to use to sign/issue the credentials - you will need to copy the DID that you created above into the examples below (as `issuer`). - You have created a (non-public) DID for Alice to use as her `credentialSubject.id` - this is required for Alice to sign the proof (the `credentialSubject.id` is not required, but then the provided presentation can't be verified). -To issue a credential, use the `/issue-credential-2.0/send` (or `/issue-credential-2.0/create-offer`) endpoint, you can test with this example payload (just replace the "connection_id", "issuer" key, "credentialSubject.id" and "proofType" with appropriate values: +To issue a credential, use the `/issue-credential-2.0/create-offer` endpoint. (You can also use the `/issue-credential-2.0/send`) endpoint, if, as mentioned above, you have included the `--no-auto` when starting both of the agents.) + +You can test with this example payload (just replace the "connection_id", "issuer" key, "credentialSubject.id" and "proofType" with appropriate values: ``` { @@ -174,6 +180,8 @@ To see the issued credential, call the `/credentials/w3c` endpoint on Alice's ad } ``` +If you *don't* see the credential in your wallet, look up the credential exchange record (in alice's admin api - `/issue-credential-2.0/records`) and check the state. If the state is `credential-received`, then the credential has been received but not stored, in this case just call the `/store` endpoint for this credential exchange. + ## Building More Realistic JSON-LD Credentials diff --git a/demo/alice-local.sh b/demo/alice-local.sh index babc85b491..b1639fc90a 100755 --- a/demo/alice-local.sh +++ b/demo/alice-local.sh @@ -1,7 +1,7 @@ #!/bin/bash # this runs the Faber example as a local instace of instance of aca-py # you need to run a local von-network (in the von-network directory run "./manage start --logs") -# ... and you need to install the local aca-py python libraries locally ("pip install -r ../requriements.txt -r ../requirements.indy.txt -r ../requirements.bbs.txt") +# ... and you need to install the local aca-py python libraries locally ("pip install -r ../requirements.txt -r ../requirements.indy.txt -r ../requirements.bbs.txt") # the following will auto-respond on connection and credential requests, but not proof requests PYTHONPATH=.. ../bin/aca-py start \ diff --git a/demo/faber-local.sh b/demo/faber-local.sh index 7471c31b67..4cfe6edae4 100755 --- a/demo/faber-local.sh +++ b/demo/faber-local.sh @@ -1,7 +1,7 @@ #!/bin/bash # this runs the Faber example as a local instace of instance of aca-py # you need to run a local von-network (in the von-network directory run "./manage start --logs") -# ... and you need to install the local aca-py python libraries locally ("pip install -r ../requriements.txt -r ../requirements.indy.txt -r ../requirements.bbs.txt") +# ... and you need to install the local aca-py python libraries locally ("pip install -r ../requirements.txt -r ../requirements.indy.txt -r ../requirements.bbs.txt") # the following will auto-respond on connection and credential requests, but not proof requests PYTHONPATH=.. ../bin/aca-py start \ diff --git a/demo/features/0586-sign-transaction.feature b/demo/features/0586-sign-transaction.feature index 1a66ef69ab..261800926d 100644 --- a/demo/features/0586-sign-transaction.feature +++ b/demo/features/0586-sign-transaction.feature @@ -25,6 +25,7 @@ Feature: RFC 0586 Aries sign (endorse) transactions functions | --mediation | --mediation | driverslicense | | --multitenant | --multitenant | driverslicense | | --mediation --multitenant | --mediation --multitenant | driverslicense | + | --multitenant --multi-ledger | --multitenant --multi-ledger | driverslicense | @T001.1-RFC0586 @GHA diff --git a/demo/features/taa-txn-author-acceptance.feature b/demo/features/taa-txn-author-acceptance.feature index 55d5790227..ac8274c1ec 100644 --- a/demo/features/taa-txn-author-acceptance.feature +++ b/demo/features/taa-txn-author-acceptance.feature @@ -17,6 +17,8 @@ Feature: TAA Transaction Author Agreement related tests | --taa-accept | driverslicense | | --taa-accept --multitenant | driverslicense | | --taa-accept --revocation | driverslicense | + | --taa-accept --multi-ledger | driverslicense | + | --taa-accept --multitenant --multi-ledger | driverslicense | @T001a-TAA @taa_required Scenario Outline: accept the ledger TAA and write to the ledger via endorser diff --git a/demo/multi_ledger_config.yml b/demo/multi_ledger_config.yml index 3290f50d5e..2c423b8d51 100644 --- a/demo/multi_ledger_config.yml +++ b/demo/multi_ledger_config.yml @@ -1,5 +1,9 @@ +#- id: local +# is_production: true +# genesis_url: 'http://$LEDGER_HOST:9000/genesis' - id: bcorvinTest is_production: true + is_write: true genesis_url: 'http://test.bcovrin.vonx.io/genesis' - id: greenlightTest is_production: true diff --git a/demo/multi_ledger_config_bdd.yml b/demo/multi_ledger_config_bdd.yml new file mode 100644 index 0000000000..14f7919fe1 --- /dev/null +++ b/demo/multi_ledger_config_bdd.yml @@ -0,0 +1,11 @@ +- id: local + is_production: true + is_write: true + genesis_url: 'http://$LEDGER_HOST:9000/genesis' +- id: bcorvinTest + is_production: true +# is_write: true + genesis_url: 'http://test.bcovrin.vonx.io/genesis' +- id: greenlightTest + is_production: true + genesis_url: 'http://dev.greenlight.bcovrin.vonx.io/genesis' diff --git a/demo/runners/agent_container.py b/demo/runners/agent_container.py index e8f1e6e7ef..87da5528da 100644 --- a/demo/runners/agent_container.py +++ b/demo/runners/agent_container.py @@ -1306,9 +1306,11 @@ async def create_agent_with_args(args, ident: str = None): ) multi_ledger_config_path = None + genesis = None if "multi_ledger" in args and args.multi_ledger: multi_ledger_config_path = "./demo/multi_ledger_config.yml" - genesis = await default_genesis_txns() + else: + genesis = await default_genesis_txns() if not genesis and not multi_ledger_config_path: print("Error retrieving ledger genesis transactions") sys.exit(1) diff --git a/demo/runners/support/agent.py b/demo/runners/support/agent.py index 8398df1279..1ec42565dc 100644 --- a/demo/runners/support/agent.py +++ b/demo/runners/support/agent.py @@ -213,6 +213,7 @@ def __init__( self.agency_wallet_did = self.did self.agency_wallet_key = self.wallet_key + self.multi_write_ledger_url = None if self.genesis_txn_list: updated_config_list = [] with open(self.genesis_txn_list, "r") as stream: @@ -225,6 +226,10 @@ def __init__( "$LEDGER_HOST", str(self.external_host) ) updated_config_list.append(config) + if "is_write" in config and config["is_write"]: + self.multi_write_ledger_url = config["genesis_url"].replace( + "/genesis", "" + ) with open(self.genesis_txn_list, "w") as file: documents = yaml.dump(updated_config_list, file) @@ -479,7 +484,10 @@ async def register_did( # if registering a did for issuing indy credentials, publish the did on the ledger self.log(f"Registering {self.ident} ...") if not ledger_url: - ledger_url = LEDGER_URL + if self.multi_write_ledger_url: + ledger_url = self.multi_write_ledger_url + else: + ledger_url = LEDGER_URL if not ledger_url: ledger_url = f"http://{self.external_host}:9000" data = {"alias": alias or self.ident} @@ -501,6 +509,7 @@ async def register_did( await asyncio.sleep(3.0) nym_info = data else: + log_msg("using ledger: " + ledger_url + "/register") resp = await self.client_session.post( ledger_url + "/register", json=data ) diff --git a/docker/Dockerfile.bdd b/docker/Dockerfile.bdd index cacf38b6aa..d2e6c2098a 100644 --- a/docker/Dockerfile.bdd +++ b/docker/Dockerfile.bdd @@ -4,5 +4,6 @@ FROM faber-alice-demo RUN pip3 install --no-cache-dir -r demo/requirements.behave.txt WORKDIR ./demo +ADD demo/multi_ledger_config_bdd.yml ./demo/multi_ledger_config.yml RUN chmod a+w . ENTRYPOINT ["behave"] diff --git a/docs/GettingStartedAriesDev/CredentialRevocation.md b/docs/GettingStartedAriesDev/CredentialRevocation.md index 8674a54e57..79eaad141c 100644 --- a/docs/GettingStartedAriesDev/CredentialRevocation.md +++ b/docs/GettingStartedAriesDev/CredentialRevocation.md @@ -151,3 +151,33 @@ further customize notification handling. If the argument `--monitor-revocation-notification` is used on startup, a webhook with the topic `revocation-notification` and a payload containing the thread ID and comment is emitted to registered webhook urls. + +## Manually Creating Revocation Registries + +The process for creating revocation registries is completely automated - when you create a Credential Definition with revocation enabled, a revocation registry is automatically created (in fact 2 registries are created), and when a registry fills up, a new one is automatically created. + +However the Aca-Py admin api supports endpoints to explicitely create a new revocation registry, if you desire. + +There are several endpoints that must be called, and they must be called in this order: + +1. Create revoc registry `POST /revocation/create-registry` + + - you need to provide the credential definition id and the size of the registry + +2. Fix the tails file URI `PATCH /revocation/registry/{rev_reg_id}` + + - here you need to provide the full URI that will be written to the ledger, for example: + +``` +{ + "tails_public_uri": "http://host.docker.internal:6543/VDKEEMMSRTEqK4m7iiq5ZL:4:VDKEEMMSRTEqK4m7iiq5ZL:3:CL:8:faber.agent.degree_schema:CL_ACCUM:3cb5c439-928c-483c-a9a8-629c307e6b2d" +} +``` + +3. Post the revoc def to the ledger `POST /revocation/registry/{rev_reg_id}/definition` + + - if you are an author (i.e. have a DID with restricted ledger write access) then this transaction may need to go through an endorser + +4. Write the tails file `PUT /revocation/registry/{rev_reg_id}/tails-file` + + - the tails server will check that the registry definition is already written to the ledger diff --git a/docs/generated/aries_cloudagent.protocols.coordinate_mediation.v1_0.rst b/docs/generated/aries_cloudagent.protocols.coordinate_mediation.v1_0.rst index ca2bc3dae6..fb05fd04d8 100644 --- a/docs/generated/aries_cloudagent.protocols.coordinate_mediation.v1_0.rst +++ b/docs/generated/aries_cloudagent.protocols.coordinate_mediation.v1_0.rst @@ -43,6 +43,14 @@ aries\_cloudagent.protocols.coordinate\_mediation.v1\_0.message\_types module :undoc-members: :show-inheritance: +aries\_cloudagent.protocols.coordinate\_mediation.v1\_0.normalization module +---------------------------------------------------------------------------- + +.. automodule:: aries_cloudagent.protocols.coordinate_mediation.v1_0.normalization + :members: + :undoc-members: + :show-inheritance: + aries\_cloudagent.protocols.coordinate\_mediation.v1\_0.route\_manager module ----------------------------------------------------------------------------- diff --git a/docs/generated/aries_cloudagent.resolver.rst b/docs/generated/aries_cloudagent.resolver.rst index c3aa28279c..7732543e90 100644 --- a/docs/generated/aries_cloudagent.resolver.rst +++ b/docs/generated/aries_cloudagent.resolver.rst @@ -33,14 +33,6 @@ aries\_cloudagent.resolver.did\_resolver module :undoc-members: :show-inheritance: -aries\_cloudagent.resolver.did\_resolver\_registry module ---------------------------------------------------------- - -.. automodule:: aries_cloudagent.resolver.did_resolver_registry - :members: - :undoc-members: - :show-inheritance: - aries\_cloudagent.resolver.routes module ---------------------------------------- diff --git a/open-api/openapi.json b/open-api/openapi.json index d7a5599378..2be5598c83 100644 --- a/open-api/openapi.json +++ b/open-api/openapi.json @@ -1,7 +1,7 @@ { "swagger" : "2.0", "info" : { - "version" : "v1.0.0-rc0", + "version" : "v1.0.0-rc1", "title" : "Aries Cloud Agent" }, "tags" : [ {