Submit Externally Signed Transactions
Submit Externally Signed Transactions - Part 2
Complete Part 1 before proceeding.
The tutorial illustrates the external signing process using two external parties, Alice and Bob,
leveraging the same Ping Daml Template used in Part 1 of the tutorial.
In Part 1
Alicecreated aPingcontract.In Part 2
Bobexercises theRespondchoice on the contract and archives it.
The majority of the work involved in external transaction signing was completed in Part 1. The key addition in Part 2 is utilizing the Ping contract created earlier through explicit disclosure and executing the Respond choice on that contract. The overall process remains similar to Part 1.
Important
This tutorial is for demo purposes. The code snippets should not be used directly in a production environment.
Setup
To proceed, gather the following information:
Bob’s Party ID, protocol signing private key, and protocol signing public key fingerprintSynchronizer ID of the synchronizer to which the participant is connected
gRPC Ledger API endpoint
ping_created_event: Event retrieved in the last step of Part 1.contract_id: ID of the contract created in Part 1.
This information should already be known from the onboarding tutorial and the first part of the external signing tutorial.
Python
If you are following this tutorial in Python, generate gRPC Python classes by following the setup instructions in the README in the example folder.
Exercise Respond Choice
This tutorial does not repeat the material covered in Part 1 regarding transaction preparation, validation, signing, and execution, as these steps remain largely the same. Instead, it highlights the key differences from Part 1.
Prepare the transaction
ping_exercise_command = commands_pb2.Command(
exercise=commands_pb2.ExerciseCommand(
template_id=ping_template_id,
contract_id=contract_id,
choice="Respond",
choice_argument=value_pb2.Value(
record=value_pb2.Record(record_id=None, fields=[])
),
)
)
prepare_exercise_request = interactive_submission_service_pb2.PrepareSubmissionRequest(
user_id=user_id,
command_id=str(uuid.uuid4()),
act_as=[responder],
read_as=[responder],
synchronizer_id=synchronizer_id,
commands=[ping_exercise_command],
# We need to explicitly disclosed the ping contract we created earlier
disclosed_contracts=[
commands_pb2.DisclosedContract(
template_id=template_id,
contract_id=contract_id,
created_event_blob=created_event_blob,
synchronizer_id=synchronizer_id,
)
],
)
prepare_exercise_response = iss_client.PrepareSubmission(prepare_exercise_request)
The Prepare request is very similar to the one from Part 1, with the following differences:
act_as: Now theresponder,Bob, instead of theinitiator,Alice. This makes sense becauseBobis the one exercising the choice on the contract.commands: The command is now anExercise``command instead of a ``Createcommand. Notably it requires thecontract_idfrom Part 1.disclosed_contracts: The serialized representation of contracts required to process the transaction.
Metadata
The only significant difference with Part 1 in the metadata is: disclosed_events.
This field now contains the input Ping contract. It is also included in the hash of the transaction.
Important
Like in Part 1, the transaction must be validated, hashed and signed.
The hash computation and signature is performed by the execute_and_get_contract_id function provided at the end of Part 1, as shown in the next section.
Submit and observe archived contract
execute_and_get_contract_id(
prepared_exercise_transaction,
responder,
responder_private_key,
responder_fingerprint,
hashing_scheme_version,
)
# The contract was archived by exercising the choice, we get an archived event this time
contract_events = get_events(responder, contract_id)
if contract_events.HasField("archived"):
print(
f"Ping contract with ID {contract_events.archived.archived_event.contract_id} has been archived"
)
else:
raise Exception("Expected an archive event")
By querying the event service and filtering for the contract ID, an archived event is observed, confirming that the contract has been successfully archived.
This concludes the external signing tutorial.
The code used in this tutorial is available in the examples/08-interactive-submission folder and can be run with
python interactive_submission.py run-demo
Tooling
The scripts mentioned in this tutorial can be used as tools for testing and development purposes
Decode base64 encoded prepared transaction to JSON
./setup.sh
python daml_transaction_util.py --decode --base64 <base64_encoded_transaction>
Compute hash of base64 encoded prepared transaction
./setup.sh
python daml_transaction_util.py --hash --base64 <base64_encoded_transaction>