Repository: hyperledger/aries-cloudagent-python

Issue:
/present-proof-2.0/send-proposal throws exception on the verifying side
I'm trying to send a indy proof proposal via /present-proof-2.0/send-proposal, as I learned this endpoint now expects a proof request vs the v1 proposal. So to replicate the v1 behavior I'm sending a very specific proof request that describes my intended proposal as close as possible. So this is my payload:

```json
{
    "by_format": {
        "pres_proposal": {
            "indy": {
                "name": "Test V2",
                "version": "2.0",
                "requested_attributes": {
                    "iban": {
                        "name": "iban",
                        "restrictions": [
                            {
                                "schema_id": "M6Mbe3qx7vB4wpZF4sBRjt:2:bank_account:1.0",
                                "cred_def_id": "EraYCDJUPsChbkw7S1vV96:3:CL:571:bob-bank-04",
                                "attr::iban::value": "mytestvalue"
                            }
                        ]
                    }
                },
                "requested_predicates": {}
            }
        }
    }
}
```

This works on the proofing side, but the verifier logs the following exception:

````
2021-11-01 14:42:08,959 aries_cloudagent.core.conductor ERROR Exception in message handler:
Traceback (most recent call last):
  File "/home/indy/.pyenv/versions/3.6.13/lib/python3.6/site-packages/aries_cloudagent/core/dispatcher.py", line 197, in handle_message
    await handler(context, responder)
  File "/home/indy/.pyenv/versions/3.6.13/lib/python3.6/site-packages/aries_cloudagent/protocols/present_proof/v2_0/handlers/pres_proposal_handler.py", line 64, in handle
    comment=context.message.comment,
  File "/home/indy/.pyenv/versions/3.6.13/lib/python3.6/site-packages/aries_cloudagent/protocols/present_proof/v2_0/manager.py", line 135, in create_bound_request
    request_data,
  File "/home/indy/.pyenv/versions/3.6.13/lib/python3.6/site-packages/aries_cloudagent/protocols/present_proof/v2_0/formats/indy/handler.py", line 117, in create_bound_request
    indy_proof_request["name"] = request_data.get("name") or "proof-request"
AttributeError: 'NoneType' object has no attribute 'get'
````

By looking at the handler this kind of makes sense, because the variable that handles the request is assigned as a None type as a default which probably means it is not assigned as intended.

```python
  async def create_bound_request(
        self,
        pres_ex_record: V20PresExRecord,
        request_data: dict = None,
    )
        // ...
        indy_proof_request["name"] = request_data.get("name") or "proof-request"
```


Discussion:
Also ran into this, @shaangill025 are you currently working on a solution for this?

Resolving patch:
diff --git a/aries_cloudagent/protocols/present_proof/v2_0/formats/indy/handler.py b/aries_cloudagent/protocols/present_proof/v2_0/formats/indy/handler.py
--- a/aries_cloudagent/protocols/present_proof/v2_0/formats/indy/handler.py
+++ b/aries_cloudagent/protocols/present_proof/v2_0/formats/indy/handler.py
@@ -114,21 +114,26 @@ async def create_bound_request(
         indy_proof_request = pres_ex_record.pres_proposal.attachment(
             IndyPresExchangeHandler.format
         )
-        indy_proof_request["name"] = request_data.get("name") or "proof-request"
-        indy_proof_request["version"] = request_data.get("version") or "1.0"
-        indy_proof_request["nonce"] = (
-            request_data.get("nonce") or await generate_pr_nonce()
-        )
+        if request_data:
+            indy_proof_request["name"] = request_data.get("name", "proof-request")
+            indy_proof_request["version"] = request_data.get("version", "1.0")
+            indy_proof_request["nonce"] = (
+                request_data.get("nonce") or await generate_pr_nonce()
+            )
+        else:
+            indy_proof_request["name"] = "proof-request"
+            indy_proof_request["version"] = "1.0"
+            indy_proof_request["nonce"] = await generate_pr_nonce()
         return self.get_format_data(PRES_20_REQUEST, indy_proof_request)
 
     async def create_pres(
         self,
         pres_ex_record: V20PresExRecord,
-        request_data: dict = {},
+        request_data: dict = None,
     ) -> Tuple[V20PresFormat, AttachDecorator]:
         """Create a presentation."""
         requested_credentials = {}
-        if request_data == {}:
+        if not request_data:
             try:
                 proof_request = pres_ex_record.pres_request
                 indy_proof_request = proof_request.attachment(


Test patch:
diff --git a/aries_cloudagent/protocols/present_proof/v2_0/tests/test_manager.py b/aries_cloudagent/protocols/present_proof/v2_0/tests/test_manager.py
--- a/aries_cloudagent/protocols/present_proof/v2_0/tests/test_manager.py
+++ b/aries_cloudagent/protocols/present_proof/v2_0/tests/test_manager.py
@@ -553,7 +553,7 @@ async def test_receive_proposal(self):
 
             assert px_rec.state == V20PresExRecord.STATE_PROPOSAL_RECEIVED
 
-    async def test_create_bound_request(self):
+    async def test_create_bound_request_a(self):
         comment = "comment"
 
         proposal = V20PresProposal(
@@ -587,6 +587,34 @@ async def test_create_bound_request(self):
         assert ret_px_rec is px_rec
         px_rec.save.assert_called_once()
 
+    async def test_create_bound_request_b(self):
+        comment = "comment"
+
+        proposal = V20PresProposal(
+            formats=[
+                V20PresFormat(
+                    attach_id="indy",
+                    format_=ATTACHMENT_FORMAT[PRES_20_PROPOSAL][
+                        V20PresFormat.Format.INDY.api
+                    ],
+                )
+            ],
+            proposals_attach=[
+                AttachDecorator.data_base64(INDY_PROOF_REQ_NAME, ident="indy")
+            ],
+        )
+        px_rec = V20PresExRecord(
+            pres_proposal=proposal.serialize(),
+            role=V20PresExRecord.ROLE_VERIFIER,
+        )
+        px_rec.save = async_mock.CoroutineMock()
+        (ret_px_rec, pres_req_msg) = await self.manager.create_bound_request(
+            pres_ex_record=px_rec,
+            comment=comment,
+        )
+        assert ret_px_rec is px_rec
+        px_rec.save.assert_called_once()
+
     async def test_create_bound_request_no_format(self):
         px_rec = V20PresExRecord(
             pres_proposal=V20PresProposal(