Skip to content

Commit c2ec492

Browse files
committed
Add support for endorser write author DID
Signed-off-by: Ian Costanzo <ian@anon-solutions.ca>
1 parent 98f5537 commit c2ec492

11 files changed

Lines changed: 319 additions & 67 deletions

File tree

aries_cloudagent/ledger/routes.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
TransactionManagerError,
2727
)
2828
from ..protocols.endorse_transaction.v1_0.models.transaction_record import (
29+
TransactionRecord,
2930
TransactionRecordSchema,
3031
)
3132
from ..protocols.endorse_transaction.v1_0.util import (
@@ -295,18 +296,29 @@ async def register_ledger_nym(request: web.BaseRequest):
295296
)
296297
endorser_did = endorser_info["endorser_did"]
297298

299+
meta_data = {"did": did, "verkey": verkey, "alias": alias, "role": role}
298300
success = False
299301
txn = None
300302
async with ledger:
301303
try:
302-
(success, txn) = await ledger.register_nym(
303-
did,
304-
verkey,
305-
alias,
306-
role,
307-
write_ledger=write_ledger,
308-
endorser_did=endorser_did,
309-
)
304+
# if we are an author check if we have a public DID or not
305+
write_ledger_nym_transaction = True
306+
# special case - if we are an author with no public DID
307+
if create_transaction_for_endorser:
308+
public_info = await ledger.get_wallet_public_did()
309+
if not public_info:
310+
write_ledger_nym_transaction = False
311+
success = False
312+
txn = {"signed_txn": json.dumps(meta_data)}
313+
if write_ledger_nym_transaction:
314+
(success, txn) = await ledger.register_nym(
315+
did,
316+
verkey,
317+
alias,
318+
role,
319+
write_ledger=write_ledger,
320+
endorser_did=endorser_did,
321+
)
310322
except LedgerTransactionError as err:
311323
raise web.HTTPForbidden(reason=err.roll_up)
312324
except LedgerError as err:
@@ -321,7 +333,6 @@ async def register_ledger_nym(request: web.BaseRequest):
321333
)
322334
)
323335

324-
meta_data = {"did": did, "verkey": verkey, "alias": alias, "role": role}
325336
if not create_transaction_for_endorser:
326337
# Notify event
327338
await notify_register_did_event(context.profile, did, meta_data)
@@ -340,12 +351,21 @@ async def register_ledger_nym(request: web.BaseRequest):
340351
# if auto-request, send the request to the endorser
341352
if context.settings.get_value("endorser.auto_request"):
342353
try:
354+
endorser_write_txn = not write_ledger_nym_transaction
343355
transaction, transaction_request = await transaction_mgr.create_request(
344356
transaction=transaction,
357+
author_goal_code=TransactionRecord.REGISTER_PUBLIC_DID
358+
if endorser_write_txn
359+
else None,
360+
signer_goal_code=TransactionRecord.WRITE_DID_TRANSACTION
361+
if endorser_write_txn
362+
else None,
363+
endorser_write_txn=endorser_write_txn,
345364
# TODO see if we need to parameterize these params
346365
# expires_time=expires_time,
347366
# endorser_write_txn=endorser_write_txn,
348367
)
368+
txn = transaction.serialize()
349369
except (StorageError, TransactionManagerError) as err:
350370
raise web.HTTPBadRequest(reason=err.roll_up) from err
351371

aries_cloudagent/protocols/endorse_transaction/v1_0/controller.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
ENDORSE_TRANSACTION = "aries.transaction.endorse"
66
REFUSE_TRANSACTION = "aries.transaction.refuse"
77
WRITE_TRANSACTION = "aries.transaction.ledger.write"
8+
WRITE_TRANSACTION = "aries.transaction.ledger.write"
9+
WRITE_DID_TRANSACTION = "aries.transaction.ledger.write_did"
10+
REGISTER_PUBLIC_DID = "aries.transaction.register_public_did"
811

912

1013
class Controller:
@@ -15,4 +18,10 @@ def __init__(self, protocol: str):
1518

1619
def determine_goal_codes(self) -> Sequence[str]:
1720
"""Return defined goal_codes."""
18-
return [ENDORSE_TRANSACTION, REFUSE_TRANSACTION, WRITE_TRANSACTION]
21+
return [
22+
ENDORSE_TRANSACTION,
23+
REFUSE_TRANSACTION,
24+
WRITE_TRANSACTION,
25+
WRITE_DID_TRANSACTION,
26+
REGISTER_PUBLIC_DID,
27+
]

aries_cloudagent/protocols/endorse_transaction/v1_0/handlers/endorsed_transaction_response_handler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ async def handle(self, context: RequestContext, responder: BaseResponder):
4545
(
4646
transaction,
4747
transaction_acknowledgement_message,
48-
) = await mgr.complete_transaction(transaction=transaction)
48+
) = await mgr.complete_transaction(transaction, False)
4949

5050
await responder.send_reply(
5151
transaction_acknowledgement_message,

aries_cloudagent/protocols/endorse_transaction/v1_0/manager.py

Lines changed: 81 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ async def create_request(
118118
signed_request: dict = None,
119119
expires_time: str = None,
120120
endorser_write_txn: bool = None,
121+
author_goal_code: str = None,
122+
signer_goal_code: str = None,
121123
):
122124
"""
123125
Create a new Transaction Request.
@@ -142,8 +144,12 @@ async def create_request(
142144
"context": TransactionRecord.SIGNATURE_CONTEXT,
143145
"method": TransactionRecord.ADD_SIGNATURE,
144146
"signature_type": TransactionRecord.SIGNATURE_TYPE,
145-
"signer_goal_code": TransactionRecord.ENDORSE_TRANSACTION,
146-
"author_goal_code": TransactionRecord.WRITE_TRANSACTION,
147+
"signer_goal_code": signer_goal_code
148+
if signer_goal_code
149+
else TransactionRecord.ENDORSE_TRANSACTION,
150+
"author_goal_code": author_goal_code
151+
if author_goal_code
152+
else TransactionRecord.WRITE_TRANSACTION,
147153
}
148154
transaction.signature_request.clear()
149155
transaction.signature_request.append(signature_request)
@@ -233,6 +239,7 @@ async def create_endorse_response(
233239

234240
transaction._type = TransactionRecord.SIGNATURE_RESPONSE
235241
transaction_json = transaction.messages_attach[0]["data"]["json"]
242+
ledger_response = {}
236243

237244
async with self._profile.session() as session:
238245
wallet: BaseWallet = session.inject_or(BaseWallet)
@@ -266,9 +273,40 @@ async def create_endorse_response(
266273
raise LedgerError(reason=reason)
267274

268275
async with ledger:
269-
endorsed_msg = await shield(
270-
ledger.txn_endorse(transaction_json, endorse_did=endorser_did_info)
276+
# check our goal code!
277+
txn_goal_code = (
278+
transaction.signature_request[0]["signer_goal_code"]
279+
if transaction.signature_request
280+
and "signer_goal_code" in transaction.signature_request[0]
281+
else TransactionRecord.ENDORSE_TRANSACTION
271282
)
283+
if txn_goal_code == TransactionRecord.ENDORSE_TRANSACTION:
284+
endorsed_msg = await shield(
285+
ledger.txn_endorse(transaction_json, endorse_did=endorser_did_info)
286+
)
287+
elif txn_goal_code == TransactionRecord.WRITE_DID_TRANSACTION:
288+
# get DID info from transaction.meta_data
289+
meta_data = json.loads(transaction_json)
290+
(success, txn) = await shield(
291+
ledger.register_nym(
292+
meta_data["did"],
293+
meta_data["verkey"],
294+
meta_data["alias"],
295+
meta_data["role"],
296+
)
297+
)
298+
# we don't have an endorsed transaction so just return did meta-data
299+
ledger_response = {
300+
"result": {
301+
"txn": {"type": "1", "data": {"dest": meta_data["did"]}}
302+
},
303+
"meta_data": meta_data,
304+
}
305+
endorsed_msg = json.dumps(ledger_response)
306+
else:
307+
raise TransactionManagerError(
308+
f"Invalid goal code for transaction record:" f" {txn_goal_code}"
309+
)
272310

273311
# need to return the endorsed msg or else the ledger will reject the
274312
# eventual transaction write
@@ -278,7 +316,7 @@ async def create_endorse_response(
278316
"message_id": transaction.messages_attach[0]["@id"],
279317
"context": TransactionRecord.SIGNATURE_CONTEXT,
280318
"method": TransactionRecord.ADD_SIGNATURE,
281-
"signer_goal_code": TransactionRecord.ENDORSE_TRANSACTION,
319+
"signer_goal_code": txn_goal_code,
282320
"signature_type": TransactionRecord.SIGNATURE_TYPE,
283321
"signature": {endorser_did: endorsed_msg or endorser_verkey},
284322
}
@@ -291,8 +329,12 @@ async def create_endorse_response(
291329
async with self._profile.session() as session:
292330
await transaction.save(session, reason="Created an endorsed response")
293331

294-
if transaction.endorser_write_txn:
295-
ledger_response = await self.complete_transaction(transaction)
332+
if (
333+
transaction.endorser_write_txn
334+
and txn_goal_code == TransactionRecord.ENDORSE_TRANSACTION
335+
):
336+
# running as the endorser, we've been asked to write the transaction
337+
ledger_response = await self.complete_transaction(transaction, True)
296338
endorsed_transaction_response = EndorsedTransactionResponse(
297339
transaction_id=transaction.thread_id,
298340
thread_id=transaction._id,
@@ -310,6 +352,7 @@ async def create_endorse_response(
310352
signature_response=signature_response,
311353
state=state,
312354
endorser_did=endorser_did,
355+
ledger_response=ledger_response,
313356
)
314357

315358
return transaction, endorsed_transaction_response
@@ -357,7 +400,9 @@ async def receive_endorse_response(self, response: EndorsedTransactionResponse):
357400

358401
return transaction
359402

360-
async def complete_transaction(self, transaction: TransactionRecord):
403+
async def complete_transaction(
404+
self, transaction: TransactionRecord, endorser: bool = False
405+
):
361406
"""
362407
Complete a transaction.
363408
@@ -371,24 +416,34 @@ async def complete_transaction(self, transaction: TransactionRecord):
371416
The updated transaction
372417
373418
"""
419+
374420
ledger_transaction = transaction.messages_attach[0]["data"]["json"]
375421

376-
ledger = self._profile.inject(BaseLedger)
377-
if not ledger:
378-
reason = "No ledger available"
379-
if not self._profile.context.settings.get_value("wallet.type"):
380-
reason += ": missing wallet-type?"
381-
raise TransactionManagerError(reason)
422+
# check if we (author) have requested the endorser to write the transaction
423+
if (endorser and transaction.endorser_write_txn) or (
424+
(not endorser) and (not transaction.endorser_write_txn)
425+
):
426+
ledger = self._profile.inject(BaseLedger)
427+
if not ledger:
428+
reason = "No ledger available"
429+
if not self._profile.context.settings.get_value("wallet.type"):
430+
reason += ": missing wallet-type?"
431+
raise TransactionManagerError(reason)
382432

383-
async with ledger:
384-
try:
385-
ledger_response_json = await shield(
386-
ledger.txn_submit(ledger_transaction, sign=False, taa_accept=False)
387-
)
388-
except (IndyIssuerError, LedgerError) as err:
389-
raise TransactionManagerError(err.roll_up) from err
433+
async with ledger:
434+
try:
435+
ledger_response_json = await shield(
436+
ledger.txn_submit(
437+
ledger_transaction, sign=False, taa_accept=False
438+
)
439+
)
440+
except (IndyIssuerError, LedgerError) as err:
441+
raise TransactionManagerError(err.roll_up) from err
442+
443+
ledger_response = json.loads(ledger_response_json)
390444

391-
ledger_response = json.loads(ledger_response_json)
445+
else:
446+
ledger_response = ledger_transaction
392447

393448
transaction.state = TransactionRecord.STATE_TRANSACTION_ACKED
394449

@@ -397,7 +452,7 @@ async def complete_transaction(self, transaction: TransactionRecord):
397452

398453
# this scenario is where the endorser is writing the transaction
399454
# (called from self.create_endorse_response())
400-
if transaction.endorser_write_txn:
455+
if endorser and transaction.endorser_write_txn:
401456
return ledger_response
402457

403458
connection_id = transaction.connection_id
@@ -733,6 +788,9 @@ async def endorsed_txn_post_processing(
733788
would be stored in wallet.
734789
"""
735790

791+
if isinstance(ledger_response, str):
792+
ledger_response = json.loads(ledger_response)
793+
736794
ledger = self._profile.inject(BaseLedger)
737795
if not ledger:
738796
reason = "No ledger available"

aries_cloudagent/protocols/endorse_transaction/v1_0/models/transaction_record.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@
99
)
1010
from .....messaging.valid import UUIDFour
1111

12-
from ..controller import ENDORSE_TRANSACTION, REFUSE_TRANSACTION, WRITE_TRANSACTION
12+
from ..controller import (
13+
ENDORSE_TRANSACTION,
14+
REFUSE_TRANSACTION,
15+
WRITE_TRANSACTION,
16+
WRITE_DID_TRANSACTION,
17+
REGISTER_PUBLIC_DID,
18+
)
1319

1420

1521
class TransactionRecord(BaseExchangeRecord):
@@ -40,6 +46,8 @@ class Meta:
4046
ENDORSE_TRANSACTION = ENDORSE_TRANSACTION
4147
REFUSE_TRANSACTION = REFUSE_TRANSACTION
4248
WRITE_TRANSACTION = WRITE_TRANSACTION
49+
WRITE_DID_TRANSACTION = WRITE_DID_TRANSACTION
50+
REGISTER_PUBLIC_DID = REGISTER_PUBLIC_DID
4351

4452
FORMAT_VERSION = "dif/endorse-transaction/request@v1.0"
4553

aries_cloudagent/protocols/endorse_transaction/v1_0/routes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ async def transaction_write(request: web.BaseRequest):
710710
(
711711
tx_completed,
712712
transaction_acknowledgement_message,
713-
) = await transaction_mgr.complete_transaction(transaction=transaction)
713+
) = await transaction_mgr.complete_transaction(transaction, False)
714714
except StorageError as err:
715715
raise web.HTTPBadRequest(reason=err.roll_up) from err
716716

aries_cloudagent/protocols/endorse_transaction/v1_0/tests/test_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ async def test_complete_transaction(self):
427427
(
428428
transaction_record,
429429
transaction_acknowledgement_message,
430-
) = await self.manager.complete_transaction(transaction_record)
430+
) = await self.manager.complete_transaction(transaction_record, False)
431431
save_record.assert_called_once()
432432

433433
assert transaction_record.state == TransactionRecord.STATE_TRANSACTION_ACKED

0 commit comments

Comments
 (0)