How To Have Your Cake and Eat It with Daml-on-Corda
Daml-on-Corda allows the open source Daml smart contract language to be used as an alternative to Kotlin (or Java) on the Corda open source blockchain platform. This article looks at the benefits of the 'Initiate and Accept' pattern. We show how a basic cake sale transaction can be improved using this pattern, how this can be achieved in Kotlin, and why it is more easily achieved in Daml.
This article is best understood with some knowledge of Daml and how Kotlin smart contracts are implemented on the Corda platform.
Let's consider a Kotlin contract that allows a baker to bake a cake for a customer.
When the baker gets the customer's details they can start a flow to create the cake and send it to the customer.
The customer will receive the cake using a responder flow:
Too Many Cakes are Unhealthy
This contract allows the baker to bake a cake for a customer.
However once the baker has discovered a customer's identity he can bake more and more cakes for them and that's not healthy.
With the existing contract state up there is no way for the contract verification logic to prevent this from happening.
How To Fix This ?
To solve this problem we can draw inspiration from Daml and the ‘initiate and accept’ pattern. Firstly we create a similar basic cake contract in Daml and see how Daml authorization rules control its use. We then introduce the ‘initiate and accept’ pattern to allow customer cake requests to be safely processed in Daml. Finally we apply the same pattern to the Kotlin contract to ensure the contract behaves as expected.
Let's first look at how this would look in Daml
In the Fat Baker Daml example the cake contract looks like this
The baker trying to create a Cake contract with the customer ('Ella') will result in the execution failing due to a missing authorization.
Daml contracts bestow rights and obligations on the signatory of a contract. In the example above the signatory has a right to eat the cake however the contract could also include an obligation to pay the baker.
For this reason Daml only allows a party to be a signatory if they have directly or indirectly authorised it which is not the case in the example above.
A consequence of this is that the only cakes the baker can bake are for themselves.
Initiate and Accept Pattern
With the 'initiate and accept' pattern the initiating party makes an offer to a third party which they can choose either to accept or ignore. This is how multi party agreements are reached in Daml.
We can see how this works with the Fit Baker Daml example.
Here the Cake contract stays the same but is created as the result of a CakeRequest created by the customer.
Now if the baker chooses to accept the request to bake a cake they can create a cake in the customer’s name.
Similarly we can have a CakeOffer contract where the baker makes the proposal and the customer can choose whether to accept.
Modify Kotlin contract to use Initiate and Accept
Firstly create a request state that must be consumed as part of cake creation.
We can then add contract verification to ensure everything is as it should be.
We've seen how the 'initiate and accept' pattern can be used to ensure valid behaviour.
Working with Kotlin requires a lot more code especially when it comes to validation.
Daml gets away with no explicit validation logic in this example simply by only allowing choices that result in valid states. For example when the baker accepts the cake request there is no opportunity to change the type of the cake.
Whether implementing this pattern or others on the Corda platform, development teams now have the choice of using Daml or Kotlin.