Exploring Tokenized Assets on Hedera Consensus Service: part 2
This blog series was jointly written by Tim McHale and Greg Scullard (Developer Advocates).
This is part 2 of a 4-part series. In part 1, we offered alternatives that gave greater control and privacy to token offerers through the use of a permissioned network alongside Hedera Consensus Service.
The second option for tokens using HCS – we’re getting to the heart of the reason this series exists – is to create a decentralized application.
The principles behind a HCS-based application have been covered in two prior webinars and a podcast:
- Introducing the Hedera Consensus Service (YouTube)
- Building applications with Hedera Consensus Service (YouTube)
- What is HCS - Hedera Consensus Service? (YouTube)
Let’s recap quickly.
In the context of HCS, a decentralized application is...
“A network of applications that communicate with each other using HCS”
This may seem confusing at first, so let’s break things down and relate them back to what we’re used to. This probably rings closer to home:
A distributed ledger is...
“A network of nodes that come to agreement on transactions using a common consensus protocol”
Hedera runs a number of nodes, each running identical code and when one of these nodes receives a request to issue a transaction by a client via its API, it sends the transaction to the network for consensus. When consensus is reached, each node updates its local state (Account Balance, Smart Contract Function call, etc…) as a direct result of the transaction contents.
So far so good.
So, let’s assume we have a set of servers, desktop and/or mobile devices that run the same code, or code that is functionally identical. That means that for a given input, any instance of this code, wherever it’s running will result in the same output.
Those could be considered to be nodes in the Hedera context.
We now obviously need some sort of consensus between all these application instances (let’s call them decentralized application nodes from now on), we need a way for them to share changes and to do so in a fair, reliable, and deterministic manner. This is where HCS enters stage left.
If a decentralized application node receives a trigger from its operator (or one of its users), such as a transfer of 20 tokens from Alice to Bob. The decentralized application node would construct a message (the equivalent of a transaction from a Hedera node client) and submit it to Hedera using a Consensus Service transaction.
Once the Hedera network has come to consensus and shared the result with mirror nodes, the mirror nodes can broadcast the result of the Consensus transaction to all the decentralized application node, which can in turn apply the necessary calculations to transfer 20 tokens from Alice to Bob.
They would of course also perform a series of checks to ensure the state isn’t being compromised, such as verifying that Alice’s balance is sufficient.
There you have it, your own decentralized application, running on as many “nodes” as you desire, all synchronised by Hedera Consensus Service message transactions.
What would the architecture look like?
Let’s look at different ways of deploying our decentralized application with increasing degrees of decentralization.
This server would be a single node running the decentralized application (maybe that’s not all that decentralized, but bear with me) and all clients would communicate with this server to transact and query state. While centralized (and hardly distributed), this has the benefit of all operations being public, if the code for the server was available through open-source for example, anyone could run a copy of the server software, subscribe to the same topic(s) and see for themselves that the server operator isn’t being malicious.
There remains a concern that the server operator could be malicious with regards to fairness (it could delay, indefinitely hold, or re-order client requests, for example). One mitigation would be for clients to submit their operations directly to HCS, the server operator would thus be unable to act maliciously in respect of fairness.
Each server acts as a decentralized application node and clients may choose any server to submit their operations or queries to.
This increases the decentralization of the application. There is no reliance on a single server operator.
Furthermore, this introduces the possibly for clients to query servers randomly to mitigate any potential malicious behaviour, it is in the interest of every server to act properly or risk being excluded from the decentralized application network.
Mobile or desktop applications
The most decentralized option is for each end user to be able to run their own application node via a desktop or mobile application.
Users can trust their own application when it comes to queries and they don’t have to rely on one or more server operators to maintain the application network.
Own mirror node(s)?
The choice whether to run your own mirror node(s) - or even to allow individual users to do so - to serve your application network is up to you. Running and maintaining one or more mirror nodes will have a cost, whether this is desirable will depend on the business model and objectives of the application network.
Let’s see some code already
Patience, it’s almost time.
We’ve built an example token project in Java to illustrate how an ERC-20 token might be implemented using HCS in the context of an application network.
The project will enable you to use a single HCS topic to manage a token. Operations to construct, mint, transfer, get balances, etc… are supported, just like an ERC-20 token.
The project implements all the necessary building blocks to get you started, improve upon to create more complex token types (such as ERC-721), or use as a foundation for a non-token related implementation.
The example has been kept simple on purpose, we could have built persistence to a database, we could have given it a REST API, but since these are bread and butter for us developers, we didn’t feel necessary to include here.
Broadly speaking a decentralized application on HCS requires the following building blocks:
- A state model, this is where token details, addresses or accounts, balances, etc… are kept
- A means to interact with a user, we’re using command line inputs in the example, but a REST API(or other) would be a suitable alternative
- A means of sending messages to HCS by way of HCS Transactions to achieve consensus
- A means of subscribing to mirror node notifications
- And finally, processing of the notifications such that state is updated accordingly.
That may seem like a lot of work, but most of it is highly reusable. Let’s compare and contrast with a Solidity implementation; I’ve highlighted the areas where custom work is required.
There is little difference here between the two as we can see, the state model and logic is obviously custom work, it will vary with each implementation, although in the context of tokens, by expanding upon the example, we could be close to a fully reusable solution already.
There are significant benefits to this approach however:
- Encryption and obfuscation of messages becomes possible
- Throughput at the speed of Hedera consensus
- Flexibility in choice of application language (even a mix of languages is possible provided the final applications are functionally identical), this opens up the possibility of better unit testing, code analysis and broader adoption by a developer community that doesn’t necessarily want to learn yet another language
- Significantly reduced transaction costs
There are a few other considerations we should pay attention to, which we'll discuss in the next section.
In part 3 of the series, we dive into code with a working example, comparing a ERC-20 token to how it could begin to be implemented using Hedera Consensus Service.