Corda Chain Snipping & The Reissuance CorDapp

Thor Gilman
Corda
Published in
7 min readApr 16, 2021

This post focuses on the new chain snipping feature released in Corda 4.7. The official Corda documentation for that feature can be found here. We will review what chain snipping is and how to go about utilizing the Reissuance CorDapp in your own CorDapps.

The Transaction Backchain

When you would like to update a state in Corda, you must provide the old version of that state as an input to the transaction. When you run the transaction, contract logic is executed to ensure that the old version of that state is allowed to evolve into the new version. However, how can we be assured that the old version of that state was created in accordance with proper contract logic? We need to go back in time and check the contract logic for how that older state was created. Then we need to check the contract logic for the state that evolved into the older state. And so on and so on. This will happen recursively until we reach the original issuance of that state. In Corda, this process is referred to as backchain verification.

While this might seem like a tedious process, there is good news. If a node has already verified a state’s transaction backchain and has that backchain cached in their vault, then there is no reason to verify the backchain each time. Only new participants to a state must retrieve the backchain from a counterparty and run backchain verification.

Below we can see an example of how backchain verification is performed. On the right, Alice is attempting to pay Bob with some Cash. To determine if the Cash is a valid state, Bob needs to recursively check the entire backchain for that Cash state to make sure it was properly issued onto the ledger.

Backchain Verification Example

While backchain verification is a critically important feature of Corda that helps to ensure the validity of data, it does come with some tradeoffs. For long-lived states, transaction backchains can sometimes become problematic.

If a state represents an asset, and that asset is traded between parties thousands of times (or more) then you can potentially run into issues with performance. If that state is traded to a new party that has not seen the states backchain, it will need to receive the entire backchain from its peers and recursively verify the chain all the way back to that state’s original issuance. While Corda 4.4 introduced bulk backchain fetching to remediate this issue through fetching entire transaction backchains in a single call, it is still time intensive to verify the contract logic for very long backchains.

Additionally, transaction backchains may cause concern for some privacy issues. In the previous example above with Alice & Bob, it’s possible that Dan may not want Bob to see the transaction he did with Alice to exchange the bond for cash. There is a concept of confidential identities in Corda which partially solves for this, however we won’t be exploring that here.

Chain Snipping

In order to prevent these issues with backchain verification, we can use a process called chain snipping. In this process, a party would decide on when to create a break in the chain, exit that state and then in a separate transaction reissue a new state with the same data. While this might seem like a simple solution, there are real concerns about what is the best chain snipping process to ensure ledger integrity. Because two different Corda transactions are running to perform chain snipping, it isn’t an atomic operation. While implementations of chain snipping have been created in the past, there hasn’t been a clear and secure way to perform it. Until now…

The Reissuance CorDapp

In Corda 4.7, R3 released the Reissuance CorDapp as the standard way to perform chain snipping in the safest way possible. A “requester” (some node that wants to snip a chain) will ask the original issuer of that state to reissue that state. As we’ve mentioned, chain snipping is not atomic as the issuer could choose not to reissue the state after it is exited. The Reissuance CorDapp solves this by having the issuer re-issue an encumbered (locked) state before the original state is deleted and allow the requester to unlock the re-issued state immediately after the original state is deleted. Encumbrance is a lesser-known concept in Corda that forces state A (the encumbered state) to only be consumed if state B (the encumbering state) is also present in the transaction.

Let’s quickly go through the entirety of the reissuance process. We will refer to the state we are reissuing as an “AssetState” but the Reissuance CorDapp is generic and can be applied to any Corda state.

  1. Requesting a Reissuance (Tx 1): The requesting party who wishes to snip the chain creates a ReissuanceRequest state and shares that state with the issuer as well as the relevant transaction backchain.
  2. Accepting a Reissuance Request (Tx 2): The issuer will accept the reissuance request and issue an encumbered ReissuanceLock state as well as a new version of the relevant AssetState which is also encumbered. Because they are both encumbered, both states must be consumed in the same transaction. This prevents the reissued AssetState from being updated unless the ReissuanceLock is updated and set to inactive. (The issuer can also reject the reissuance request however we won’t be covering that in detail here).
  3. Exiting the original state (Tx 3): The requester will exit the original state using whatever exit command that state has. It is a requirement that there are no output states to this transaction.
  4. Unlocking the reissued state (Tx 4): Once the original state is exited, the requester can immediately unlock the reissued states as long as they provide the original state’s exit transaction as an attachment. This acts as proof that the state can now be reissued. Both the ReissuanceLock and the AssetState become unencumbered so that the AssetState can be used in the future. (Alternatively, if the AssetState is updated and not exited, then it is now impossible to unlock the reissued state and the requester should call a separate flow to delete both the ReissuanceLock and reissued asset state).

The below diagram depicts this process in more detail using Corda Design Language (CDL).

Reissuance State Evolution CDL

Setting up the Reissuance CorDapp

We will be referencing the Git repository found here for the remainder of this post. This is a very simple CorDapp with an AssetState that is issued by a designated issuer on the network. Then that AssetState can be transferred between different peers on the network as well as exited. This CorDapp is intentionally simple so we can focus more on the capabilities of the Reissuance CorDapp.

Let’s start with how you would get the Reissuance CorDapp added as a dependency within your own project.

First add the following properties to your constants.properties file. While the state that you want to be reissued doesn’t necessarily need to utilize the Tokens SDK, the reissuance CorDapp will still need the Tokens SDK workflows as a dependency (It is planned that this Tokens SDK dependency will be removed in future versions of the Reissuance CorDapp).

reissuanceReleaseGroup=com.r3.corda.lib.reissuance
reissuanceReleaseVersion=1.0-GA
tokensReleaseVersion = 1.2
tokensReleaseGroup = com.r3.corda.lib.tokens

Now, let’s retrieve these values from within our root build.gradle’s ext{} block.

reissuance_release_group = constants.getProperty("reissuanceReleaseGroup")
reissuance_release_version = constants.getProperty("reissuanceReleaseVersion")
tokens_release_group = constants.getProperty("tokensReleaseGroup")
tokens_release_version = constants.getProperty("tokensReleaseVersion")

We also want to add the corda-lib repository so we can access the Reissuance & Tokens libraries.

allprojects {
apply from: "${rootProject.projectDir}/repositories.gradle"
apply plugin: 'kotlin'

repositories {
mavenLocal()
jcenter()
mavenCentral()
maven { url 'https://software.r3.com/artifactory/corda' }
maven { url 'https://jitpack.io' }
maven { url 'https://software.r3.com/artifactory/corda-lib' }

Next, add the following to the dependencies{} block in both your root build.gradle as well as your workflows build.gradle file.

dependencies {
...
cordapp "$reissuance_release_group:reissuance-cordapp-contracts:$reissuance_release_version"
cordapp "$reissuance_release_group:reissuance-cordapp-workflows:$reissuance_release_version"
cordapp "$tokens_release_group:tokens-workflows:$tokens_release_version"
}

Implement Custom Flow Responders

As the requirements & business logic of different CorDapps can vary, we need to implement our own responders to some of the flows within the Reissuance CorDapp. Abstract classes are provided for the needed responders, however, we will need to inherit from those classes with our own implementation.

These implementations are fairly basic and it is recommended that more complex business logic is added for real use cases.

  • The custom ReissueStates responder implements ReissueStatesResponder
  • The custom UnlockReissuedStates responder implements UnlockReissuedStatesResponder
  • The custom DeleteReissuedStatesAndLock responder implements DeleteReissuedStatesAndLockResponder

This final responder is needed for when a reissuance fails which isn’t explored in detail here.

Reissuance Testing

Finally, let’s take a look at how one would run these flows to perform a reissuance. While you can just follow along below, the following code can be found within the FlowTests file within the Git repository here. The below test demonstrates the entire reissuance process as described previously.

Note: A helper method “runFlow()” is being used here to abstract away the running of the MockNetwork & usage of futures.

While we don’t discuss what an “unhappy path” might look like for reissuance in this document, there is also an “unhappy path” unit test in the Git repository for those interested. It’s also possible to reissue multiple states in a single reissuance request which also isn’t explored in this CorDapp.

Hopefully this document has provided some insight into how to get started with this exciting new Corda feature. For additional information on Reissuance in Corda please see the official Corda documentation that can be found here.

Want to learn more about building amazing blockchain applications on Corda? Be sure to visit corda.net and sign up for one of our newsletters for the latest updates.

— Thor Gilman is a Solutions Engineer at R3, an enterprise blockchain software firm working with a global ecosystem of more than 350 participants across multiple industries from both the private and public sectors to develop on Corda, its open-source blockchain platform, and Corda Enterprise, a commercial version of Corda for enterprise usage.

--

--