Cryptoasset Framework on Intel's Hyperledger Sawtooth: Part One

Here at PokitDok we are developing DokChain™ using Intel's blockchain platform Hyperledger Sawtooth. Unlike Ethereum or Bitcoin, Sawtooth purposefully does not come with a cryptocurrency. However, as it is the purpose of DokChain to facilitate a multitude of healthcare transactions across industries, monetary transfer will play an essential role in the network's operations. As part of the company's overall strategy it was imperative we implement a secure crypoasset component on top of Sawtooth.

Of course the immediate and obvious concern for any currency, crypto or not, is security. Given that DokChain implements smart contracts handling private health information (PHI), security is imperative for all components of the network. However, currency on a blockchain network is an obvious target for a malicious actor, and so we implement additional safeguards with respect to the cryptocurrency.

Two options for cryptocurrency implementation are the Unspent Transaction Output (UTXO) popularized by Bitcoin, or an account design used, for example, in Ethereum. The account design is the simpler of the two. In this design every user has an account that records the amount of coin they own, and account functionalities allow spending coins from one account to another. For a discussion about the difference between the UTXO and the account design click here. In DokChain, we have chosen to use the account design for our cryptocurrency.

Before we dive into some of the details regarding our implementation, at this point it is probably a good idea to define some terminology. For more complete definitions see this blog by Ted Tanner, Jr., Co-founder & CTO of PokitDok.

Sawtooth transaction transaction Sawtooth provides details in their documentation here. Essentially a transaction is a smart contract executed on the DokChain.
Global State Store Store See Sawtooth's documentation here. The Store is the Merkle tree storing DokChain's blocks.
Jane Jane A user on DokChain. Note: when Jane executes a transaction, we really mean Jane's pubkey.
DokChain's coin $CURE A reference to the cryptocurrency on DokChain.

The first challenge we face in providing additional guards for $CURE comes from the fact that every transaction has the ability to modify the Store. Since using the account design implies that Jane's $CURE balance is simply stored somewhere in the Store, every transaction has the ability to modify Jane's $CURE. This has the unpleasant consequence that in order to guarantee the security of the currency, it is not sufficient to only guarantee the program correctness of the transactions related to managing the coin, but also to make sure all the other transactions do not touch coin addresses in the Store.

DokChain Coin Namespacee /></p>
<p>Fortunately, Sawtooth has implemented a namespace feature that can be used to better shelter the coin. <a href=Sawtooth's namespace mechanism allows separating the Store into different namespaces. Furthermore, read/write permissions for the various namespaces can be granted on a Sawtooth transaction family basis. So, we implement a coin namespace and a coin transaction family (see diagram above). All $CURE balances are stored in the coin namespace portion of the Store, and only the coin transaction family has write permissions to this namespace. This greatly simplifies securing the coin. Instead of having to inspect every transaction for manipulation of coin, only the transaction in the coin transaction family must be analyzed. As a corollary, any coin transfer on DokChain must use the transactions implemented by the coin transaction family.

Does this limit the functionality of transactions on the network? For example, suppose that Jane would like an eligibility check with her insurance company through DokChain, and the cost for the check is 10 $CURE. The most obvious solution would be to code the coin transfer logic into the eligibility check transaction. In our design, however, this is not possible. The eligibility check transaction is associated with a Sawtooth transaction family that does not have write permission to the coin namespace. Instead, Jane must execute an eligibility check transaction and a coin transfer transaction separately.

This creates a potential trust problem. Which transaction comes first? Must Jane trust her insurance company and first send the coin, or does the insurance company have to trust Jane? Fortunately, through Sawtooth's batching mechanism neither is required. Since a batch is the atomic unit in Sawtooth, batching the eligibility check transaction and the coin transfer transaction ensures that either both transactions execute successfully or neither do. This illustrates the general solution. Any transaction that requires the transfer of coin can be decoupled with the coin transfer transaction executed separately. If a strong coupling is desired, these transactions can be batched together.

Now that we have separated the coin namespace isolating the coin transactions, the next challenge is to ensure the validity of the transactions in the coin transaction family. For this we reference the ERC20 Token Standard. Precisely, we implement the transfer, approve, and transfer_from transactions. Additionally we implement a free_approvals transaction to allow for unused approvals to be released.

The transfer transaction is pretty straightforward. The parameters are to_pubkey and amount, and the effect is for amount to be transferred from the originator (the equivalent of Ethereum's msg.sender) to to_pubkey. The transactions approve and transfer_from are a little less straightforward. The idea is to first approve the transfer of coin using the approve transaction, and then later the approved pubkey calls transfer_from to actually transfer the coin. The approve/transfer_from use case will be clarified below.

Let's get a little more technical and go through an example exposing the changes to the coin data structure. We have

COIN_DATA = {'spendable_amount': int, 'approvals': dict()}

where approvals is a dictionary mapping each approved pubkey to the approved amount and a release_time. For the example diagrammed below, we shorthand spendable_amount to spendable, amount to amt, release_time to rt, and use a terse representation of a datetime. Assume that the current time is 09:00.

DokChain Coin Transfer Example

Here Jane's goal is an eligibility check on DokChain. She first creates an approval allowing Insurer to collect 10 $CURE. However, she (accidentally) submits a release time equal to the current time, 09:00. The Insurer, wary of the possibility that Jane might try to free her approval after receiving the eligibility check but before the Insurer is about to execute transfer_from, informs Jane that she must correct the release time. So, Jane frees the original approval and creates another approval with a later release time. The eligibility check transaction executes, and then Insurer calls transfer_from batched with a transfer_fee transaction.

What is this transfer_fee transaction? To answer this with clarity we must first digress slightly and discuss DokChain's organization. DokChain will operate as a private blockchain network with a relatively small number of Nodes. The Nodes will be hosted by DokChain Alliance members, and each of these Nodes will run validators responsible for validating transactions submitted on DokChain. Each of these validators has a pubkey, and hence are eligible to receive $CURE. Similar to Bitcoin and Ethereum these validators will receive "minted" coin for each block they validate.

This minting is discussed in some detail in the DokChain Whitepaper by Bryan Smith, Chief Scientist at PokitDok. For now, it is enough to know the simple fact from basic economics, that this minting reward could fall short of the actual market-determined value of validating a DokChain block. Hence, much like Bitcoin's fee and Ethereum's gas, we require a mechanism to augment this potential minting reward shortfall. This is where the transfer_fee transaction enters the picture. This transfer_fee transaction is a special transaction that pays the block's PoET winning validator(1) for validating the transaction. It provides additional reward to validators for processing transactions and maintaining the DokChain network.

In the example diagrammed above, notice the use of batching in regards to this transfer_fee transaction. The batching example given earlier promoted batching using a trustless argument, which is not very well motivated for DokChain. However, batching the transfer_fee transaction is important. If the original transaction (transfer_from in the above example) fails, then we do not want the fee to be transferred. This is ensured if they are batched together.

We now remark on a few details that the above example exposes. First notice that the approvals dictionary essentially implements the escrowing of coin. Its place in COIN_DATA is slightly misleading because this gives a sense that Jane owns, and hence can modify, these approvals. This is not the case. The only access Jane has to these approvals is through the approve transaction or the free_approvals transaction. The former only allows adding approvals, and the later only frees approvals after the specified release time.

The informed reader may, at this point, be a little wary of a concept of "time" on a blockchain. The problem of course is that there is no way to ensure that all nodes have the same concept of "now" when they are validating a block. This is somewhat remedied in Bitcoin and Ethereum by timestamping each block, a feature that will also exist in an upcoming version  of Sawtooth. In this case, however, we do not actually need a timestamp. Since the release time is explicitly represented in Jane's approvals and the free_approvals code is known, Insurer can make its own decision on whether the release time is too early or not. If Jane does not agree with Insurer's conservative estimate of the "now" computation on DokChain, then they can take that argument off-chain!

The final technical detail that we would like to discuss is the implementation of the transfer_fee transaction. The challenge here is that at the time of the transfer_fee transaction creation, the PoET winner of the block is not known. To solve this problem DokChain's current implementation uses something akin to an off-chain oracle. The transfer_fee transaction transfers the fee from the originator to a fixed address on DokChain. There is only one pubkey, set by DokChain's governance through Sawtooth's settings transaction family, that can read/write to this fixed address. Then, the oracle is activated periodically to retrospectively distribute the fees stored at this address to the PoET winning validators. This somewhat unsatisfactory and cumbersome solution is only temporary, however. The soon-to-be released version of Sawtooth has a BatchInjector concept which allows for a much cleaner design in regards to this transfer_fee transaction.

For all those companies that are planning on or have already launched an initial coin offering, we will be providing this technology via our DokChain software development kit in the near future.

Using Hyperledger Sawtooth we have implemented a cryptoasset framework on DokChain. Employing Sawtooth's namespace concept, we are able to restrict coin account write access to a single transaction family. Furthermore, motivated by the ERC20 Token Standard, we implemented only a select few (assiduously designed) smart contracts within this coin transaction family.


1 PoET is used in Sawtooth by default, but other consensus algorithms are pluggable such as PBFT.

About Luke Owens

Luke is a data scientist at PokitDok working on blockchain technology. He has a PhD in mathematics from the University of South Carolina. Previously, Luke worked as a quantitative analyst developing an interest in machine learning and implementing risk and valuation models. Cryptoassets on various blockchains now pique his interest.

View All Posts

Leave a Reply

Your email address will not be published.