In Daml, you must specify who can view data using stakeholder annotations in your template definitions. To change who can see the data, you would typically need to recreate a contract with a template that computes different stakeholder parties. Explicit contract disclosure allows you to delegate contract read rights to non-stakeholders using off-ledger data distribution. This supports efficient, scalable data sharing on the ledger.Documentation Index
Fetch the complete documentation index at: https://docs.canton.network/llms.txt
Use this file to discover all available pages before exploring further.
Explicit disclosure is activated by default. To deactivate it, configure
participants.participant.ledger-api.enable-explicit-disclosure = false.- You want to provide proof of the price data for a stock transaction. Instead of subscribing to price updates and potentially being inundated with thousands of price updates every minute, you could serve the price data through a traditional Web 2.0 API. You can then use that API to feed only the current price back into the ledger at the time of use. You still get the same validation and security, but reduce the amount of data being transferred manyfold.
- You want to run an open market on ledger. Rather than making all bids and asks explicitly visible to all marketplace users, you serve market data though standard Web 2.0 APIs. At the point of use, the available bids and asks are fed back into the transactions to get the same activeness and correctness guarantees that would be provided had they been shared though the observer mechanism.
Contract Read Delegation
Contract read delegation allows a party to acquire read rights during command submission over a contract of which it is neither a stakeholder nor an informee. As an example application where read delegation could be used, consider a simplified trade between two parties. In this example, party Seller owns a unit of Digital AssetStock issued by the StockExchange party. As the issuer of the stock, StockExchange also publishes the stock’s PriceQuotation as public data, which can be used for settling trades at the correct market value. The Seller announces an offer to sell its stock publicly by creating an Offer contract that can be exercised by anyone who can pay the correct market value in terms of IOU units.
On the other side, party Buyer owns an IOU with 10 monetary units, which it wants to use to acquire Seller’s stock.
The Daml templates used to model the above-mentioned trade are outlined below.
Offer_Accept on the offerCid contract. But how can Buyer exercise a choice on a contract on which it is neither a stakeholder nor a prior informee? The same question applies to Buyer’s visibility over the stockCid and `priceQuotationCid contracts.
If Buyer plainly exercises the choice as shown in the snippet below, the submission will fail with an error citing missing visibility rights over the involved contracts.
— Command fails with missing visibility over the contracts for buyer
_ their contracts to any party desiring to execute such a trade. Buyer can attach the disclosed contracts to the command submission that is exercising Offer_Accept on Seller’s offerCid, thus bypassing the visibility restriction over the contracts.
The Ledger API uses the disclosed contracts attached to command submissions for resolving contract and key activeness lookups during command interpretation. This means that usage of a disclosed contract effectively bypasses the visibility restriction of the submitting party over the respective contract. However, the authorization restrictions of the Daml model still apply: the submitted command still needs to be well authorized. The actors need to be properly authorized to execute the action.
How do stakeholders disclose contracts to submitters?
The disclosed contract’s details can be fetched by the contract’s stakeholder from the contract’s associated CreatedEvent, which can be read from the Ledger API via the state and update queries. The stakeholder can then share the disclosed contract details to the submitter off-ledger (outside of Daml) by conventional means, such as HTTPS, SFTP, or e-mail. A DisclosedContract can be constructed from the fields of the same name from the original contract’sCreatedEvent.
The
created_event_blob field in CreatedEvent (used to construct the DisclosedContract) is populated only on demand for GetUpdates, GetUpdateTrees, and GetActiveContracts streams.To learn more, see configuring event format.Attaching a disclosed contract to a command submission
A disclosed contract can be attached as part of theCommand’s disclosed_contracts and requires the following fields (see DisclosedContract for content details) to be populated from the original CreatedEvent (see above):
- template_id - The contract’s template id.
- contract_id - The contract id.
- created_event_blob - The contract’s representation as an opaque blob encoding.
Only contracts created starting with Canton 2.8 can be shared as disclosed contracts. In earlier versions, the CreatedEvent does not have the required populated
created_event_blob field and cannot be used as disclosed contracts.Trading the stock with explicit disclosure
In the example above, Buyer does not have visibility over thestockCid, priceQuotationCid and offerCid contracts, so Buyer must provide them as disclosed contracts in the command submission exercising Offer_Accept. To do so, the contracts’ stakeholders must fetch them from the ledger and make them available to the Buyer.
Then, the Buyer attaches the disclosed contract payloads to the command submission that accepts the offer.
These last two steps are executed using the new Daml Script functions supporting explicit disclosure: queryDisclosure and submitWithDisclosures.
For an example using Java bindings for client applications, see the Java Bindings StockExchange example project.
Safeguards
In the example above, what if the Buyer is malicious and wants to pay less than the official price quotation for Seller’s stock? Buyer might try to do so by modifying the receiveddisclosedPriceQuotation payload received from the StockExchange by setting a lower value in the contract’s arguments and then using the forged payload as a disclosed contract in the command submission exercising Offer_Accept on Seller’s offer.
Contract authentication
Scenarios like the one exemplified above are not possible due to a new technical feature introduced with the explicit contract disclosure feature: Daml contract authentication. More specifically, each contract’s arguments, template-id, signatories, keys, etc. are incorporated into the contract’s contract-id as a hash over all the relevant information, ensuring that any tampering leads to a different contract-id than the one submitted. All the honest participants involved in the transaction then catch the misalignment. In the example above, if the Buyer’s participant is honest it cannot be tricked and would reject the submission with aDISCLOSED_CONTRACT_AUTHENTICATION_FAILED. If Buyer’s participant is also malicious and submits a confirmation request with the malformed payload, the other participants involved in the transaction detect the misalignment and reject the request.
Business logic safeguards
As good practice, each Daml application workflow should have business logic preconditions that safeguard against misuse. In our example, theOffer_Accept choice has a flexible controller (buyer) that is provided as an argument. Since any party can exercise the choice by providing the disclosedOffer disclosed contract at command submission time, the choice body should contain safeguards that disallow malicious use, modeled in our example as Daml asserts.
— Assert the quotation issuer and asset name
priceQuotation.issuer === quotationProducer
priceQuotation.stockName === asset.stockName
When modeling Daml workflows using disclosed contracts, such safeguards assure:
- a disclosed contract’s user that its contents are validated against expected conditions.
- a disclosed contract’s owner that it is used within the expected agreement.
Offer_Accept ensure that the price quotation is coming from a party that the Seller is trusting (Issuer) and that it actually matches stock that the Seller intends to sell.