Skip to content

Commit

Permalink
Merge branch 'main' into fix/dif-claim-format-designation
Browse files Browse the repository at this point in the history
  • Loading branch information
ianco authored Jan 5, 2023
2 parents 54e6464 + a28441a commit 31e10a2
Show file tree
Hide file tree
Showing 44 changed files with 1,562 additions and 192 deletions.
39 changes: 39 additions & 0 deletions .github/workflows/nightly-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Nightly Tests

on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:

jobs:
tests:
name: Tests
strategy:
fail-fast: false
matrix:
os: ["ubuntu-latest"]
python-version: ["3.7", "3.8", "3.9", "3.10"]
include:
- os: "ubuntu-20.04"
python-version: "3.6"
uses: ./.github/workflows/tests.yml
with:
python-version: ${{ matrix.python-version }}
os: ${{ matrix.os }}

tests-indy:
name: Tests (Indy)
strategy:
fail-fast: false
matrix:
os: ["ubuntu-latest"]
python-version: ["3.7", "3.8", "3.9", "3.10"]
include:
- os: "ubuntu-20.04"
python-version: "3.6"

uses: ./.github/workflows/tests-indy.yml
with:
python-version: ${{ matrix.python-version }}
os: ${{ matrix.os }}
indy-version: "1.16.0"
20 changes: 20 additions & 0 deletions .github/workflows/pr-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: PR Tests

on:
pull_request:

jobs:
tests:
name: Tests
uses: ./.github/workflows/tests.yml
with:
python-version: "3.6"
os: "ubuntu-20.04"

tests-indy:
name: Tests (Indy)
uses: ./.github/workflows/tests-indy.yml
with:
python-version: "3.6"
indy-version: "1.16.0"
os: "ubuntu-20.04"
58 changes: 58 additions & 0 deletions .github/workflows/tests-indy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Tests (Indy)

on:
workflow_call:
inputs:
python-version:
required: true
type: string
indy-version:
required: true
type: string
os:
required: true
type: string

jobs:
tests:
name: Test Python ${{ inputs.python-version }} on Indy ${{ inputs.indy-version }}
runs-on: ${{ inputs.os }}
steps:
- uses: actions/checkout@v3

- name: Cache image layers
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache-test
key: ${{ runner.os }}-buildx-test-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-test-
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1

- name: Build test image
uses: docker/build-push-action@v3
with:
load: true
context: .
file: docker/Dockerfile.indy
target: acapy-test
tags: acapy-test:latest
build-args: |
python_version=${{ inputs.python-version }}
indy_version=${{ inputs.indy-version }}
cache-from: type=local,src=/tmp/.buildx-cache-test
cache-to: type=local,dest=/tmp/.buildx-cache-test-new,mode=max

# Temp fix
# https://github.com/docker/build-push-action/issues/252
# https://github.com/moby/buildkit/issues/1896
- name: Move cache
run: |
rm -rf /tmp/.buildx-cache-test
mv /tmp/.buildx-cache-test-new /tmp/.buildx-cache-test
- name: Run pytest
run: |
docker run --rm acapy-test:latest
35 changes: 35 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Tests

on:
workflow_call:
inputs:
python-version:
required: true
type: string
os:
required: true
type: string

jobs:
tests:
name: Test Python ${{ inputs.python-version }}
runs-on: ${{ inputs.os }}
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ inputs.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ inputs.python-version }}
cache: 'pip'
cache-dependency-path: 'requirements*.txt'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip3 install --no-cache-dir \
-r requirements.txt \
-r requirements.askar.txt \
-r requirements.bbs.txt \
-r requirements.dev.txt
- name: Tests
run: |
pytest
9 changes: 9 additions & 0 deletions Multicredentials.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Multi-Credentials

It is a known fact that multiple AnonCreds can be combined to present a presentation proof with an "and" logical operator: For instance, a verifier can ask for the "name" claim from an eID and the "address" claim from a bank statement to have a single proof that is either valid or invalid. With the Present Proof Protocol v2, it is possible to have "and" and "or" logical operators for AnonCreds and/or W3C Verifiable Credentials.

With the Present Proof Protocol v2, verifiers can ask for a combination of credentials as proof. For instance, a Verifier can ask a claim from an AnonCreds **and** a verifiable presentation from a W3C Verifiable Credential, which would open the possibilities of Aries Cloud Agent Python being used for rather complex presentation proof requests that wouldn't be possible without the support of AnonCreds or W3C Verifiable Credentials.

Moreover, it is possible to make similar presentation proof requests using the or logical operator. For instance, a verifier can ask for either an eID in AnonCreds format or an eID in W3C Verifiable Credential format. This has the potential to solve the interoperability problem of different credential formats and ecosystems from a user point of view by shifting the requirement of holding/accepting different credential formats from identity holders to verifiers. Here again, using Aries Cloud Agent Python as the underlying verifier agent can tackle such complex presentation proof requests since the agent is capable of verifying both type of credential formats and proof types.

In the future, it would be even possible to put mDoc as an attachment with an and or or logical operation, along with AnonCreds and/or W3C Verifiable Credentials. For this to happen, Aca-Py either needs the capabilities to validate mDocs internally or to connect third-party endpoints to validate and get a response.
1 change: 1 addition & 0 deletions aries_cloudagent/admin/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down
41 changes: 33 additions & 8 deletions aries_cloudagent/config/argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 1 addition & 3 deletions aries_cloudagent/core/conductor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand All @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion aries_cloudagent/indy/models/cred_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class Meta:
unknown = EXCLUDE

prover_did = fields.Str(
requred=True,
required=True,
description="Prover DID",
**INDY_DID,
)
Expand Down
17 changes: 14 additions & 3 deletions aries_cloudagent/ledger/multiple_ledger/indy_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from ...cache.base import BaseCache
from ...core.profile import Profile
from ...ledger.base import BaseLedger
from ...ledger.error import LedgerError
from ...wallet.crypto import did_is_self_certified

Expand Down Expand Up @@ -53,7 +54,11 @@ def __init__(

async def get_write_ledger(self) -> Optional[Tuple[str, IndySdkLedger]]:
"""Return the write IndySdkLedger instance."""
return self.write_ledger_info
# return self.write_ledger_info
if self.write_ledger_info:
return (self.write_ledger_info[0], self.profile.inject_or(BaseLedger))
else:
return None

async def get_prod_ledgers(self) -> Mapping:
"""Return production ledgers mapping."""
Expand Down Expand Up @@ -83,7 +88,11 @@ async def _get_ledger_by_did(
"""
try:
indy_sdk_ledger = None
if ledger_id in self.production_ledgers:
if self.write_ledger_info and ledger_id == self.write_ledger_info[0]:
indy_sdk_ledger = await self.get_write_ledger()
if indy_sdk_ledger:
indy_sdk_ledger = indy_sdk_ledger[1]
elif ledger_id in self.production_ledgers:
indy_sdk_ledger = self.production_ledgers.get(ledger_id)
else:
indy_sdk_ledger = self.non_production_ledgers.get(ledger_id)
Expand Down Expand Up @@ -134,7 +143,9 @@ async def lookup_did_in_configured_ledgers(
cache_key = f"did_ledger_id_resolver::{did}"
if bool(cache_did and self.cache and await self.cache.get(cache_key)):
cached_ledger_id = await self.cache.get(cache_key)
if cached_ledger_id in self.production_ledgers:
if self.write_ledger_info and cached_ledger_id == self.write_ledger_info[0]:
return self.get_write_ledger()
elif cached_ledger_id in self.production_ledgers:
return (cached_ledger_id, self.production_ledgers.get(cached_ledger_id))
elif cached_ledger_id in self.non_production_ledgers:
return (
Expand Down
35 changes: 19 additions & 16 deletions aries_cloudagent/ledger/multiple_ledger/manager_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,24 +84,27 @@ def provide(self, settings: BaseSettings, injector: BaseInjector):
pool_name = config.get("pool_name")
ledger_is_production = config.get("is_production")
ledger_is_write = config.get("is_write")
ledger_pool = pool_class(
pool_name,
keepalive=keepalive,
cache=cache,
genesis_transactions=genesis_transactions,
read_only=read_only,
socks_proxy=socks_proxy,
)
ledger_instance = ledger_class(
pool=ledger_pool,
profile=self.root_profile,
)
if ledger_is_write:
write_ledger_info = (ledger_id, ledger_instance)
if ledger_is_production:
indy_sdk_production_ledgers[ledger_id] = ledger_instance
write_ledger_info = (ledger_id, None)
else:
indy_sdk_non_production_ledgers[ledger_id] = ledger_instance
ledger_pool = pool_class(
pool_name,
keepalive=keepalive,
cache=cache,
genesis_transactions=genesis_transactions,
read_only=read_only,
socks_proxy=socks_proxy,
)
ledger_instance = ledger_class(
pool=ledger_pool,
profile=self.root_profile,
)
if ledger_is_production:
indy_sdk_production_ledgers[ledger_id] = ledger_instance
else:
indy_sdk_non_production_ledgers[
ledger_id
] = ledger_instance
if settings.get_value("ledger.genesis_transactions"):
ledger_instance = self.root_profile.inject_or(BaseLedger)
ledger_id = "startup::" + ledger_instance.pool.name
Expand Down
Loading

0 comments on commit 31e10a2

Please sign in to comment.