Skip to content

Commit 12ecda3

Browse files
authored
Merge branch 'main' into feature/keylist-webhooks
2 parents c233778 + 00d97b3 commit 12ecda3

40 files changed

Lines changed: 951 additions & 84 deletions

CHANGELOG.md

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
# 0.7.4-RC1
1+
# 0.7.4-RC2
22

3-
This release consists largely of internal fixes with a few minor enhancements.
4-
There have been a lot of groups exercising ACA-Py and the updates made in this
5-
release are a reflection of those efforts. We have PRs that have been
6-
contributed by 17 different people, which is likely a record for a single ACA-Py
7-
release.
3+
The 0.7.4 release consists largely of internal fixes with a few minor
4+
enhancements. There have been a lot of groups exercising ACA-Py and the updates
5+
made in this release are a reflection of those efforts. We have PRs that have
6+
been contributed by 17 different people, which is likely a record for a single
7+
ACA-Py release.
88

99
The largest enhancement is in the area of the Hyperledger Indy endorser,
1010
enabling an instance of ACA-Py to act as an Endorser for Indy authors needed
@@ -27,6 +27,16 @@ the team at LISSI for creating the
2727
to make load testing so easy! And of course to the core ACA-Py team for
2828
addressing the findings.
2929

30+
The team has worked a lot on evolving the persistent queue (PQ) approach
31+
available in ACA-Py. We have landed on a design whereby the ability to use
32+
queues for inbound and outbound messages is within ACA-Py, with a default
33+
in-memory implementation, and the implementations of external persistent queues
34+
solutions is handled by referencing a plugin from a separate repository. There
35+
will shortly be two concrete, out-of-the-box solutions available, one for Kafka
36+
and one for Redis, and anyone else can implement their own PQ plugin as long as
37+
it uses the same ACA-Py queuing interface. Look for the new PQ repos shortly
38+
within Hyperledger Aries.
39+
3040
Several new ways to control ACA-Py configurations were added, including new
3141
startup parameters, Admin API parameters to control instances of protocols, and
3242
additional web hook notifications.
@@ -60,6 +70,9 @@ stuff needed for a growing codebase.
6070
- Feature/undelivered events [\#1694](https://github.com/hyperledger/aries-cloudagent-python/pull/1694) ([mepeltier](https://github.com/mepeltier))
6171
- Allow use of SEED when creating local wallet DID Issue-1682 Issue-1682 [\#1705](https://github.com/hyperledger/aries-cloudagent-python/pull/1705) ([DaevMithran](https://github.com/DaevMithran))
6272

73+
- Persistent Queues
74+
- Redis PQ Cleanup in preparation for enabling the uses of plugin PQ implementations \[Issue\#1659\] [\#1659](https://github.com/hyperledger/aries-cloudagent-python/pull/1690) ([shaangill025](https://github.com/shaangill025))
75+
6376
- Issue Credential, Revocation, Present Proof updates/fixes
6477
- Fix: DIF proof proposal when creating bound presentation request \[Issue\#1687\] [\#1690](https://github.com/hyperledger/aries-cloudagent-python/pull/1690) ([shaangill025](https://github.com/shaangill025))
6578
- Fix DIF PresExch and OOB request\_attach delete unused connection [\#1676](https://github.com/hyperledger/aries-cloudagent-python/pull/1676) ([shaangill025](https://github.com/shaangill025))
@@ -68,6 +81,7 @@ stuff needed for a growing codebase.
6881
- Fixes for credential details in issue-credential webhook responses [\#1668](https://github.com/hyperledger/aries-cloudagent-python/pull/1668) ([andrewwhitehead](https://github.com/andrewwhitehead))
6982
- Fix: present-proof v2 send-proposal [issue\#1474](https://github.com/hyperledger/aries-cloudagent-python/issues/1474) [\#1667](https://github.com/hyperledger/aries-cloudagent-python/pull/1667) ([shaangill025](https://github.com/shaangill025))
7083
- Fixes Issue 3b from [\#1597](https://github.com/hyperledger/aries-cloudagent-python/issues/1597): V2 Credential exchange ignores the auto-respond-credential-request
84+
- fix: Resolve Revocation Notification environment variable name collision [\#1751](https://github.com/hyperledger/aries-cloudagent-python/pull/1751) ([frostyfrog](https://github.com/frostyfrog))
7185
- fix: always notify if revocation notification record exists [\#1665](https://github.com/hyperledger/aries-cloudagent-python/pull/1665) ([TimoGlastra](https://github.com/TimoGlastra))
7286
- Revert change to send\_credential\_ack return value [\#1660](https://github.com/hyperledger/aries-cloudagent-python/pull/1660) ([andrewwhitehead](https://github.com/andrewwhitehead))
7387
- Fix usage of send\_credential\_ack [\#1653](https://github.com/hyperledger/aries-cloudagent-python/pull/1653) ([andrewwhitehead](https://github.com/andrewwhitehead))
@@ -80,6 +94,7 @@ stuff needed for a growing codebase.
8094

8195
- Mediator updates and fixes
8296
- feat: allow querying default mediator from base wallet [\#1729](https://github.com/hyperledger/aries-cloudagent-python/pull/1729) ([dbluhm](https://github.com/dbluhm))
97+
- Added async with for mediator record delete [\#1749](https://github.com/hyperledger/aries-cloudagent-python/pull/1749) ([dejsenlitro](https://github.com/dejsenlitro))
8398

8499
- Multitenacy updates and fixes
85100
- feat: create new JWT tokens and invalidate older for multitenancy [\#1725](https://github.com/hyperledger/aries-cloudagent-python/pull/1725) ([TimoGlastra](https://github.com/TimoGlastra))
@@ -96,6 +111,7 @@ stuff needed for a growing codebase.
96111
- Add an integration test for mixed proof with a revocable cred and a n… [\#1672](https://github.com/hyperledger/aries-cloudagent-python/pull/1672) ([ianco](https://github.com/ianco))
97112

98113
- Documentation and Demo Updates
114+
- Fetch from --genesis-url likely to fail in composed container [\#1746](https://github.com/hyperledger/aries-cloudagent-python/pull/1739) ([tdiesler](https://github.com/tdiesler))
99115
- Fixes logic for web hook formatter in Faber demo [\#1739](https://github.com/hyperledger/aries-cloudagent-python/pull/1739) ([amanji](https://github.com/amanji))
100116
- Multitenancy Docs Update [\#1706](https://github.com/hyperledger/aries-cloudagent-python/pull/1706) ([MonolithicMonk](https://github.com/MonolithicMonk))
101117
- [\#1674](https://github.com/hyperledger/aries-cloudagent-python/issue/1674) Add basic DOCKER\_ENV logging for run\_demo [\#1675](https://github.com/hyperledger/aries-cloudagent-python/pull/1675) ([tdiesler](https://github.com/tdiesler))

Multiledger.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ More background information including problem statement, design (algorithm) and
1414
- [Read Requests](#read-requests)
1515
- [For checking ledger in parallel](#for-checking-ledger-in-parallel)
1616
- [Write Requests](#write-requests)
17+
- [A Special Warning for TAA Acceptance](#a-special-warning-for-taa-acceptance)
1718
- [Impact on other ACA-Py function](#impact-on-other-aca-py-function)
1819

1920
## Usage
@@ -104,6 +105,25 @@ If multiple ledgers are configured then `IndyLedgerRequestsExecutor` service ext
104105

105106
On startup, the first configured applicable ledger is assigned as the `write_ledger` [`BaseLedger`], the selection is dependant on the order (top-down) and whether it is `production` or `non_production`. For instance, considering this [example configuration](#example-config-file), ledger `bcorvinTest` will be set as `write_ledger` as it is the topmost `production` ledger. If no `production` ledgers are included in configuration then the topmost `non_production` ledger is selected.
106107

108+
## A Special Warning for TAA Acceptance
109+
110+
When you run in multi-ledger mode, ACA-Py will use the `pool-name` (or `id`) specified in the ledger configuration file for each ledger.
111+
112+
(When running in single-ledger mode, ACA-Py uses `default` as the ledger name.)
113+
114+
If you are running against a ledger in `write` mode, and the ledger requires you to accept a Transaction Author Agreement (TAA), ACA-Py stores the TAA acceptance
115+
status in the wallet in a non-secrets record, using the ledger's `pool_name` as a key.
116+
117+
This means that if you are upgrading from single-ledger to multi-ledger mode, you will need to *either*:
118+
119+
- set the `id` for your writable ledger to `default` (in your `ledgers.yaml` file)
120+
121+
*or*:
122+
123+
- re-accept the TAA once you restart your ACA-Py in multi-ledger mode
124+
125+
Once you re-start ACA-Py, you can check the `GET /ledger/taa` endpoint to verify your TAA acceptance status.
126+
107127
## Impact on other ACA-Py function
108128

109129
There should be no impact/change in functionality to any ACA-Py protocols.

aries_cloudagent/askar/profile.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ async def _teardown(self, commit: bool = None):
213213
await self._handle.commit()
214214
except AskarError as err:
215215
raise ProfileError("Error committing transaction") from err
216+
if self._handle:
217+
await self._handle.close()
216218
self._handle = None
217219
self._check_duration()
218220

aries_cloudagent/config/argparse.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,20 @@ def add_arguments(self, parser: ArgumentParser):
534534
),
535535
)
536536

537+
parser.add_argument(
538+
"--block-plugin",
539+
dest="blocked_plugins",
540+
type=str,
541+
action="append",
542+
required=False,
543+
metavar="<module>",
544+
env_var="ACAPY_BLOCKED_PLUGIN",
545+
help=(
546+
"Block <module> plugin module from loading. Multiple "
547+
"instances of this parameter can be specified."
548+
),
549+
)
550+
537551
parser.add_argument(
538552
"--plugin-config",
539553
dest="plugin_config",
@@ -611,6 +625,9 @@ def get_settings(self, args: Namespace) -> dict:
611625
if args.external_plugins:
612626
settings["external_plugins"] = args.external_plugins
613627

628+
if args.blocked_plugins:
629+
settings["blocked_plugins"] = args.blocked_plugins
630+
614631
if args.plugin_config:
615632
with open(args.plugin_config, "r") as stream:
616633
settings["plugin_config"] = yaml.safe_load(stream)

aries_cloudagent/config/default_context.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ async def bind_providers(self, context: InjectionContext):
111111
async def load_plugins(self, context: InjectionContext):
112112
"""Set up plugin registry and load plugins."""
113113

114-
plugin_registry = PluginRegistry()
114+
plugin_registry = PluginRegistry(
115+
blocklist=self.settings.get("blocked_plugins", [])
116+
)
115117
context.injector.bind_instance(PluginRegistry, plugin_registry)
116118

117119
# Register standard protocol plugins

aries_cloudagent/core/plugin_registry.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import logging
44
from collections import OrderedDict
55
from types import ModuleType
6-
from typing import Sequence
6+
from typing import Sequence, Iterable
77

88
from ..config.injection_context import InjectionContext
99
from ..core.event_bus import EventBus
@@ -19,9 +19,10 @@
1919
class PluginRegistry:
2020
"""Plugin registry for indexing application plugins."""
2121

22-
def __init__(self):
22+
def __init__(self, blocklist: Iterable[str] = []):
2323
"""Initialize a `PluginRegistry` instance."""
2424
self._plugins = OrderedDict()
25+
self._blocklist = set(blocklist)
2526

2627
@property
2728
def plugin_names(self) -> Sequence[str]:
@@ -119,6 +120,9 @@ def register_plugin(self, module_name: str) -> ModuleType:
119120
"""Register a plugin module."""
120121
if module_name in self._plugins:
121122
mod = self._plugins[module_name]
123+
elif module_name in self._blocklist:
124+
LOGGER.debug(f"Blocked {module_name} from loading due to blocklist")
125+
return None
122126
else:
123127
try:
124128
mod = ClassLoader.load_module(module_name)

aries_cloudagent/core/tests/test_plugin_registry.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515

1616
class TestPluginRegistry(AsyncTestCase):
1717
def setUp(self):
18-
self.registry = PluginRegistry()
18+
self.blocked_module = "blocked_module"
19+
self.registry = PluginRegistry(blocklist=[self.blocked_module])
1920

2021
self.context = InjectionContext(enforce_typing=False)
2122
self.proto_registry = async_mock.MagicMock(
@@ -478,6 +479,23 @@ class MODULE:
478479
]
479480
assert self.registry.register_plugin("dummy") == obj
480481

482+
async def test_unregister_plugin_has_setup(self):
483+
class MODULE:
484+
setup = "present"
485+
486+
obj = MODULE()
487+
with async_mock.patch.object(
488+
ClassLoader, "load_module", async_mock.MagicMock()
489+
) as load_module:
490+
load_module.side_effect = [
491+
obj, # module
492+
None, # routes
493+
None, # message types
494+
None, # definition without versions attr
495+
]
496+
assert self.registry.register_plugin(self.blocked_module) == None
497+
assert self.blocked_module not in self.registry._plugins.keys()
498+
481499
async def test_register_definitions_malformed(self):
482500
class MODULE:
483501
no_setup = "no setup attr"

aries_cloudagent/ledger/indy.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import logging
66
import tempfile
77
from datetime import date, datetime
8+
from io import StringIO
89
from os import path
910
from time import time
1011
from typing import Sequence, Tuple, Optional
@@ -42,6 +43,17 @@
4243
GENESIS_TRANSACTION_FILE = "indy_genesis_transactions.txt"
4344

4445

46+
def _normalize_txns(txns: str) -> str:
47+
"""Normalize a set of genesis transactions."""
48+
lines = StringIO()
49+
for line in txns.splitlines():
50+
line = line.strip()
51+
if line:
52+
lines.write(line)
53+
lines.write("\n")
54+
return lines.getvalue()
55+
56+
4557
class IndySdkLedgerPoolProvider(BaseProvider):
4658
"""Indy ledger pool provider which keys off the selected pool name."""
4759

@@ -107,12 +119,28 @@ def __init__(
107119
self.cache = cache
108120
self.cache_duration = cache_duration
109121
self.genesis_transactions = genesis_transactions
122+
self.genesis_txns_cache = genesis_transactions
110123
self.handle = None
111124
self.name = name
112125
self.taa_cache = None
113126
self.read_only = read_only
114127
self.socks_proxy = socks_proxy
115128

129+
@property
130+
def genesis_txns(self) -> str:
131+
"""Get the configured genesis transactions."""
132+
if not self.genesis_txns_cache:
133+
try:
134+
txn_path = path.join(
135+
tempfile.gettempdir(), f"{self.name}_{GENESIS_TRANSACTION_FILE}"
136+
)
137+
self.genesis_txns_cache = _normalize_txns(open(txn_path).read())
138+
except FileNotFoundError:
139+
raise LedgerConfigError(
140+
"Pool config '%s' not found", self.name
141+
) from None
142+
return self.genesis_txns_cache
143+
116144
async def create_pool_config(
117145
self, genesis_transactions: str, recreate: bool = False
118146
):

aries_cloudagent/protocols/revocation_notification/definition.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,11 @@
66
"minimum_minor_version": 0,
77
"current_minor_version": 0,
88
"path": "v1_0",
9-
}
9+
},
10+
{
11+
"major_version": 2,
12+
"minimum_minor_version": 0,
13+
"current_minor_version": 0,
14+
"path": "v2_0",
15+
},
1016
]

aries_cloudagent/protocols/revocation_notification/v1_0/models/rev_notification_record.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class Meta:
2727
"rev_reg_id",
2828
"cred_rev_id",
2929
"connection_id",
30+
"version",
3031
}
3132

3233
def __init__(
@@ -38,6 +39,7 @@ def __init__(
3839
connection_id: str = None,
3940
thread_id: str = None,
4041
comment: str = None,
42+
version: str = None,
4143
**kwargs,
4244
):
4345
"""Construct record."""
@@ -47,6 +49,7 @@ def __init__(
4749
self.connection_id = connection_id
4850
self.thread_id = thread_id
4951
self.comment = comment
52+
self.version = version
5053

5154
@property
5255
def revocation_notification_id(self) -> Optional[str]:
@@ -73,6 +76,7 @@ async def query_by_ids(
7376
rev_reg_id: the rev reg id by which to filter
7477
"""
7578
tag_filter = {
79+
**{"version": "v1_0"},
7680
**{"cred_rev_id": cred_rev_id for _ in [""] if cred_rev_id},
7781
**{"rev_reg_id": rev_reg_id for _ in [""] if rev_reg_id},
7882
}
@@ -101,6 +105,7 @@ async def query_by_rev_reg_id(
101105
rev_reg_id: the rev reg id by which to filter
102106
"""
103107
tag_filter = {
108+
**{"version": "v1_0"},
104109
**{"rev_reg_id": rev_reg_id for _ in [""] if rev_reg_id},
105110
}
106111

@@ -157,3 +162,7 @@ class Meta:
157162
description="Optional comment to include in revocation notification",
158163
required=False,
159164
)
165+
version = fields.Str(
166+
description="Version of Revocation Notification to send out",
167+
required=False,
168+
)

0 commit comments

Comments
 (0)