B9lab blog

We help organisations build and engage communities, and attract and retain developers.

Follow publication

How to Design a CorDapp and Analyze Privacy Leaks Using CDL Views

--

Image by rottonara from Pixabay.

Introduction

So you were tasked to design a CorDapp; you finished gathering all the requirements and now you want to exhibit your design. How do you go about that? Do you use a UML diagram to model your states? What about contracts, how do you present the validation rules for each command? What’s the best way to show which signatures are required in a transaction? What about privacy leaks?!

Without a standardized way, this task would have become very difficult. What’s obvious and easy to understand for the business analyst, might be ambiguous and hard to digest for the client; so R3 came up with CDL Views (CorDapp Design Language Views), which is a template of shapes (like the ones that you get in Visio or Lucidchart) that helps you model states, their evolution constraints, the required signatures, and the flow of actions.

All this is achievable by using multiple views:

  • State Machine View.
  • State Evolution View.
  • State Instance View.
  • Business Process Modeling Notation View.
  • Transaction Instance View.
  • Flow Sequence View.

CDL is very extensive, and the official documentation explains it in great detail; so in this article I will show you just enough to get you going, and leave it to you to further explore and experiment with a certain CDL view.

I will use the IOU example, and sort of reverse engineer it back to the design phase.

We’ll imagine that the IOU state has 3 commands:

  • Create: To issue a new IOU.
  • Update: To amend the IOU value.
  • Exit: To pay the IOU and stop tracking it on the ledger.

How to model a State

When representing a state, there’s no need to show all the properties (e.g. linearId in a linear state); only show the ones that matter in your view. You can also have a concise version if you don’t care about showing the attributes or participants in the current view.

State Machine View

State machine views are used to model what your smart contracts (i.e. state + contract) can do.

Based on some input, the state transitions from one status to the other in a set of finite statuses; if a transition is not modeled in this view, it’s considered disallowed.

Clarification: status is an attribute that you need to add to your state if you want to enforce that certain transitions happen only at certain statuses; it’s not required otherwise.

Usually in a state contract we group the validation rules into 3 groups:

  • Shape: What are the inputs and outputs of the transaction.
  • Content: Any business rule that you can think of (e.g. lender and borrower cannot be the same).
  • Required signatures: Who are the parties that approve the transaction.

State machine views model the above constraints using:

  • State Level Constraints (SLC): These constraints are derived from one instance of the state (i.e. one state in a certain status independently from other components of the transaction). For example, we cannot create an IOU with a negative value.
  • Transitions Constraints: Those are the commands that are allowed at a certain status. For instance, when the IOU is in “amended” status we can either update it again, or exit it from the ledger.
  • Transaction Level Constraints (TLC): Unlike SLC that look at one instance of the state, TLC look at the transaction as a whole (i.e. all inputs and outputs). For instance, when we update an IOU only the value may change (i.e. the lender / borrower between the input and output must not change), when we exit an IOU its value must be 0.
  • Required Signers Constraints (SC): For each command there is a set of required signers that must approve it. For instance, to create an IOU both the lender and borrower must be required signers (imagine giving someone a loan without them asking or approving it!).
  • Multiplicity Constraints (MC): Those constraints define the number of instances of a certain state that are expected as inputs and outputs. They are pretty straight forward; the only one that needs clarification is 1:Matched which means the output state must have the same linearId as the input state. In our example, when we update the IOU value we expect one IOU output state that has the same linearId as the single input IOU state.

Now, let’s summarize and combine all of the constraints of our IOU State Machine View in one diagram (click on image to enlarge):

State Evolution View

A state evolution view shows a potential route in a state machine view, so if we look at a state machine view as the generic behavior of a class, then a state evolution view describes the behavior of an instance of that class.

For our IOU example, we’ll model the following path: Create (iou = 100) -> Update (pay 50) -> Update (pay 50) -> Exit(fully paid = no longer tracked by Corda) (click on image to enlarge):

Notice how we replaced attribute data types (e.g. value: Integer) with actual values (e.g. value: 100), and displayed the actual signers on the arrows representing the commands (e.g. Create (PartyA and PartyB)).

Privacy Leaks!

The true power of state evolution views comes when we combine 2 or more of them in one transaction; suddenly you can see how states interact with each other, who the network is, and how does each participant see the ledger from their point of view; which in return allows you to do privacy analysis of your design.

As you know, when a node receives a transaction; it resolves its input states (i.e. it verifies the transactions that generated those inputs), and if those transactions also have inputs; it will request the transactions that created those inputs and verify them as well. It will keep doing the verification process recursively going back in history until it reaches genesis (i.e. the first transaction that had only outputs and no inputs).

This process might lead to a certain node receiving transactions that it shouldn’t be aware of, for instance while resolving a transaction some party might receive a transaction that contains states that belong to a competitor; giving them advantage in the market. That’s why privacy analysis is very trivial in CorDapps design!

Let’s see an example of a bad design, how we can trace the privacy leak, and propose ideas to fix it.

Imagine we have 2 simple states: Cash and SecretDeal.

Our transaction takes 2 inputs and produces 2 outputs, where essentially Alice pays Bob to get the secret deal that he owns:

Now Bob wants to spend his Cash to get the secret deal that Carol owns:

As we know, the Cash that Bob is spending in Tx 02 is the result of what he received from Alice in Tx 01, meaning Bob is consuming the Cash state that was one of the outputs of Tx 01 as one of the inputs in Tx 02(click on image to enlarge):

The same way that Corda resolves a transaction going backwards, we start analyzing privacy leaks from the end going back to the start of our state evolution view.

Important: Analysis must always be conducted from a single party point of view, because not all participants see the same ledger (remember “on a need to know basis” concept?).

So let’s mark the start and end of our privacy analysis route from the point of view of Carol:

We can’t model the state evolution view for all of the states in our diagram; it will quickly become too busy, for instance in Tx 02 we didn’t model what transaction resulted in the SecretDeal that Carol owned; so to make diagrams more concise and to mark that privacy leak is not an issue at a certain part of it, we need a marker that says “it’s ok for this party to see whatever proceeded this state evolution” and that marker is called Privacy Chain In:

The same way that we marked our diagram with Privacy Chain In, we need a way to say “it’s ok for this party to see whatever comes after this state evolution”:

Now that we identified from who’s point of view we are looking at the ledger (i.e. Carol), set our analysis limits (privacy end / privacy start), and clarified what past and future state evolution is permitted to be viewable by our actor (privacy chain in / privacy chain out); now we can conduct our analysis.

Starting from “privacy end” we can see that when Corda wants to finalize Tx 02 it will see that there’s an input (the Cash state held by Bob), so it will request the transaction that created that Cash state (i.e Tx 01) to verify it as well, but Tx 01 has also another state, the SecretDeal that’s owned by Alice; so when Carol receives Tx 01 it will see Alice’s SecretDeal which is a privacy leak!

Let’s place our privacy leak marker on the exposed transaction:

FYI: ReceiveFinalityFlow which you call in the responder flow to finalize the transaction in your peer nodes is set by default to StatesToRecord = ONLY_RELEVANT, meaning when a node receives a transaction that has many states; it will only record the states that it is involved in as a participant, so with that default setup, a privacy leak is not a concern. Going back to our previous example, Carol won’t register in its vault the SecretDeal of Alice because she’s not a participant in that state. But since there is no guarantee how your peer nodes will implement the responder; then there’s a chance that they will set StatesToRecord = ALL_VISIBLE meaning whenever they receive a transaction, they will register all the states of that transaction whether they’re a participant or not. The same applies to observer nodes, for instance Tokens SDK has its own version of finality flow that takes sessions for observer nodes ObserverAwareFinalityFlow and in that flow the StatesToRecord = ALL_VISIBLE for observer nodes, otherwise they won’t be able to register any state; since they’re not a participant in them.

This concludes our privacy analysis using state evolution views. Of course, the example and diagrams are very simplified; I was trying to clear things for you, not blow your fuse board. The official documentation (which I will reference at the end of the article) has more elaborate examples.

Extra: Fixing the Leak

The fix depends on your concern, if it’s just the involved parties being exposed; then you can simply use AnonymousParty instead of Party:

If your concern goes beyond that, then we have to resort to a change in the design, and if you’re serious about designing great CorDapps (or impressing your Corda bootcamp crush); I strongly recommend that you read Receipts and Token Receipts patterns (also mentioned in the references section).

Receipts Pattern

The receipts pattern has many consideration and details to look after, my explanation below is the simplified version; again, I recommend that you read the detailed version in the official documentation.

In the receipts pattern we usually have 2 moving parts: the enabler, and the dependent. In our example Cash was the enabler, because moving Cash from Alice to Bob, enabled moving SecretDeal from Bob to Alice. So the transition of the enabler is a prerequisite to transition the dependent.

But as we saw, involving Cash state directly in the transaction caused a privacy leak. The receipts pattern proposes including a Receipt state which confirms that the Cash transition happened instead of including the Cash state directly; so when Alice pays Bob, the transaction has 2 outputs: the moved Cash and the Receipt confirming the move:

So let’s refactor our previous example using the receipts pattern (click on image to enlarge):

Notice how the Pay transition has now 2 outputs: the moved Cash and the Receipt confirming it, and the Transfer transition has 2 inputs: the SecretDeal and the payment Receipt.

Let’s now analyze the privacy from Carol’s point of view; adding privacy end, privacy start, privacy chain in, and privacy chain out markers (remember that this is an imaginary example, so I’m setting the scenarios):

  • Privacy End: Let’s assume that the last SecretDeal is going to be redeemed, so nothing happens after that; which is the end of our privacy route.
  • Privacy Start: Let’s assume that the first Cash state was just issued, so nothing happened before that; which is the start of our privacy route.
  • Privacy Chain In: I will imagine that it’s ok for Carol to see what happened before the first Cash state, and what happened before its SecretDeal.
  • Privacy Chain Out: I will imagine that it’s ok for Carol to see what happens after the last SecretDeal.

Now let’s start our analysis from Privacy End going back to Privacy Start(follow the blue line in the below diagram):

When Corda wants to verify Tx 02, it will request the transaction that resulted in the Receipt input state (which is when Bob paid Carol); and as you can see, downloading that transaction will also result in requesting the previous transaction (i.e. when Alice paid Bob) to verify it as well, but that’s it! Resolving Tx 02 doesn’t lead to downloading Tx 01, because they’re simply not connected. So Carol is no longer able to see Alice’s SecretDeal.

CDL Template

The template that I used to create the diagrams in this article was built by R3, and it’s publicly accessible here: https://www.lucidchart.com/invitations/accept/d56d7806-3007-456e-b770-d6ed135def5d

LucidChart is an online version of Visio, and it’s free unless you want some advanced features. To use the above template, open that link; choose the first file and open it, then File->Make a Copy, and now your copy is editable (i.e. you can copy/paste the shapes into your diagrams).

References

— — — — — — — — —

B9lab Academy has a Corda course that can take you from zero blockchain knowledge to creating cordapps that work with cash, debt and other contracts, and facilitates flexible, potentially complex settlement agreements across multiple currencies and instruments.

Still not sure? Have a look at our free Corda 101 course

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Published in B9lab blog

We help organisations build and engage communities, and attract and retain developers.

No responses yet

Write a response