Repository: hyperledger/aries-cloudagent-python

Issue:
Duplicated Schema and Definition Ids
**Context:**

- ACA-Py version: 0.7.3
- Docker image: bcgovimages/aries-cloudagent:py36-1.16-1_0.7.3
- Askar: flag on
- Postgres: flag on
- Indy: Soverin BuildNet


**Issue**
After an issuer creates a new schema and definition, when querying the schema and definition ids, response payload shows duplicated ids.

- API to query schemas: /schemas/created

<img width="631" alt="image" src="https://user-images.githubusercontent.com/16185797/170987155-a5520ebd-26cd-4bd3-97ad-d066ab0fb3d1.png">


- API to query definitions: /credential-definitions/created

<img width="640" alt="image" src="https://user-images.githubusercontent.com/16185797/170987209-5837d65d-fef7-49bd-981d-15201bf7d8ed.png">

**Expected Result**
Shouldn't show duplicated data in each response payload. 


Discussion:
This should be fixed in `0.7.4`

See: https://github.com/hyperledger/aries-cloudagent-python/pull/1721

@ianco , is the fix available in the `0.7.4-rcx` or formal `0.7.4` to be released?
it's in the `0.7.4-rcx` versions

@ianco, I've quickly tested this in `0.7.4-rc2`, the issue still remains. Could you reopen this ticket?
@yunxi-zhang the fix prevents duplicate records from being created but it doesn't remove them if you already have dups.

I just double-checked on the `main` branch and the duplicate check is working (on create schema or cred def)

@ianco, I've retested the version `0.7.4-rc2` again and found out that this issue doesn't exist if using the agent's **built-in wallet** when creating a new schema and definition, but if I use **Askar + postgres**, this issue does exist in the same scenario. Should I raise this issue in Askar?
Hi @yunxi-zhang I'll give it a try, I'm surprised there's a difference between indy-sdk and askar ...

Confirmed that when running in Askar mode, there is two entries for each schema.  Steps to replicate:

- Start von-network and Faber
- Wait until invite to copy prompt
- Run API call: http://localhost:8021/api/doc#/schema/get_schemas_created
  - Under indy -- the schema that is created is listed once, under askar, it is there twice:

```
{
  "schema_ids": [
    "LM9gLcfVkR9mD7UEV7w4BL:2:degree schema:9.13.70",
    "LM9gLcfVkR9mD7UEV7w4BL:2:degree schema:9.13.70"
  ]
}
```

If I create another schema, it too is listed twice.
@andrewwhitehead -- can you please take a look at this.  This seems like a pretty big deal in trying to move to Askar.
FYI -- to run the demo using askar, add the argument: ` --wallet-type askar` to the `./run_demo` command.
FYI I tested with:  `POSTGRES=true ./run_demo faber --wallet-type askar`, running a separate postgres database.

The create schema and create cred def check for duplicate creation (if you try to create the same schema or same cred def twice you get an error message, "... already exists", however ...

The `/schemas/created` shows 2 records for each schema
... and the `/cred-defs/created` also shows 2 records for each cred def

Either the wallet record is getting created twice, or the query is pulling duplicate records (maybe duplicate tags are getting created?)

@andrewwhitehead -- please take a look ASAP.  Thanks!

Resolving patch:
diff --git a/aries_cloudagent/ledger/indy_vdr.py b/aries_cloudagent/ledger/indy_vdr.py
--- a/aries_cloudagent/ledger/indy_vdr.py
+++ b/aries_cloudagent/ledger/indy_vdr.py
@@ -19,8 +19,6 @@
 from ..cache.base import BaseCache
 from ..core.profile import Profile
 from ..indy.issuer import IndyIssuer, IndyIssuerError, DEFAULT_CRED_DEF_TAG
-from ..messaging.credential_definitions.util import CRED_DEF_SENT_RECORD_TYPE
-from ..messaging.schemas.util import SCHEMA_SENT_RECORD_TYPE
 from ..storage.base import BaseStorage, StorageRecord
 from ..utils import sentinel
 from ..utils.env import storage_path
@@ -464,19 +462,6 @@ async def create_and_send_schema(
                 else:
                     raise
 
-            schema_id_parts = schema_id.split(":")
-            schema_tags = {
-                "schema_id": schema_id,
-                "schema_issuer_did": public_info.did,
-                "schema_name": schema_id_parts[-2],
-                "schema_version": schema_id_parts[-1],
-                "epoch": str(int(time())),
-            }
-            record = StorageRecord(SCHEMA_SENT_RECORD_TYPE, schema_id, schema_tags)
-            async with self.profile.session() as session:
-                storage = session.inject(BaseStorage)
-                await storage.add_record(record)
-
         return schema_id, schema_def
 
     async def check_existing_schema(
@@ -715,24 +700,6 @@ async def create_and_send_credential_definition(
             if not write_ledger:
                 return (credential_definition_id, {"signed_txn": resp}, novel)
 
-            # Add non-secrets record
-            schema_id_parts = schema_id.split(":")
-            cred_def_tags = {
-                "schema_id": schema_id,
-                "schema_issuer_did": schema_id_parts[0],
-                "schema_name": schema_id_parts[-2],
-                "schema_version": schema_id_parts[-1],
-                "issuer_did": public_info.did,
-                "cred_def_id": credential_definition_id,
-                "epoch": str(int(time())),
-            }
-            record = StorageRecord(
-                CRED_DEF_SENT_RECORD_TYPE, credential_definition_id, cred_def_tags
-            )
-            async with self.profile.session() as session:
-                storage = session.inject(BaseStorage)
-                await storage.add_record(record)
-
         return (credential_definition_id, json.loads(credential_definition_json), novel)
 
     async def get_credential_definition(self, credential_definition_id: str) -> dict:


Test patch:
diff --git a/aries_cloudagent/storage/tests/test_indy_storage.py b/aries_cloudagent/storage/tests/test_indy_storage.py
--- a/aries_cloudagent/storage/tests/test_indy_storage.py
+++ b/aries_cloudagent/storage/tests/test_indy_storage.py
@@ -354,7 +354,7 @@ async def test_storage_del_close(self):
                 while not mock_indy_close_search.await_count and c < 10:
                     await asyncio.sleep(0.1)
                     c += 1
-                mock_indy_close_search.assert_awaited_once_with(1)
+                mock_indy_close_search.assert_awaited_with(1)
 
             with async_mock.patch.object(  # error on close
                 indy.non_secrets, "open_wallet_search", async_mock.CoroutineMock()