Part Two—Solving Real-World Problems with Blockchain
In my last post, I said we are going to build a distributed application (DApp) that will solve a real-world problem. In this post, I will describe what that problem is and some of the practical constraints we must consider while solving it. This problem happens to exist in the payments industry where Levvel is actively engaged with many clients.
Describing the Problem
All current Person-to-Person (P2P) payment offerings use a directory that links a customer and their bank account number to an easy-to-use identifier (or alias), such as a mobile phone number or email address. These directories are unique for each P2P solution like PayPal, Venmo, Zelle and PopMoney; they are not shared. The payment directory holy grail would be a centralized, shared, common directory that might include the following features:
- Not hosted by a single organization
- Independently accessible by each financial institution (FI) participating in the shared directory, with shared maintenance and upkeep
- Used for all directory-based payments including P2P, business-to-business (B2B), and other permutations
- Will always be available to active participants, even if other participants are offline
- Accessible with read-only access for non-bank payment companies for identification and verification (ID&V) purposes
A decentralized application that leverages a smart contract(s) might offer the perfect solution for the ubiquitous payment directory described above. The smart contract would allow authorized participants to add, delete, and modify alias data that is stored in the blockchain, verified by the blockchain miners, and transmitted to all participating blockchain nodes.
Payment Directory Practical Considerations
For real-world payment directories, each FI is required to verify the customer’s ownership of the alias prior to linking it to their deposit account. Since the FI is responsible for knowing their customer and hosting customer accounts, it is only natural that they are the only authorized participants who can add or delete aliases in the directory. Companies like PayPal and Venmo could use the directory to discover what FI account number the customer has registered with the alias so they can transfer money from their internal account to the customer’s FI account when asked to do so.
For this application, the following practical considerations are assumed:
- Only FIs hosting customer accounts are authorized to add or delete aliases linked to that account
- The FI registering an alias must verify that the customer owns the alias and linked account
- For alias transfers (i.e. transfer to another FI), the owning FI must delete the alias before it can be added by the new FI. This makes the contract simpler.
- Directory participants can view the directory contents to see if an alias is registered, and what FI has registered it, but the associated account numbers are encrypted.
- All FI public keys will be available to clearing organizations to decode the encrypted account numbers.
- A trusted administrator or committee will authorize (e.g. add or delete) the blockchain node address for participating FIs. This might seem counter-intuitive for a public blockchain, but is reasonable for a private or consortium blockchain network.
Blockchains are classified as public, private, or a consortium, which is a hybrid of the two. The actual blockchain used to implement our DApp is irrelevant from a security perspective since we will build security into the contract itself. Practically, a distributed payment alias directory is best suited for a consortium blockchain network since it is not intended for a wide audience of participants.
Payment Directory Smart Contract
The term “smart contract” makes a lot of sense in the context of writing applications that verify certain conditions exist prior to initiating a payment based upon those conditions. However, blockchain can be used for much more than that. In fact, blockchain software now has an integrated virtual computer built in that can execute instructions that store and manipulate data as well as send and receive payments. Blockchain can be thought of as a distributed operating system (OS), and smart contracts are just a computer program that runs on each blockchain node. The Ethereum Virtual Machine (EVM) is the “operating system” that facilitates this magic, and the Solidity computer language is the software we will use to create our payment directory application smart contract.
Tools of the Trade
Let’s get started writing our DApp. We could open our favorite editor and start writing code but as we all know; smart developers are lazy! Why make life harder than it already is? This is where DApp development tools like Truffle and Embark come to the rescue. I haven’t tried Embark or other related tools yet, but I used Truffle for this application, and it is awesome!
Once you run the truffle init command, you will have a project structure with the following directories complete with sample files:
The following shows the project directory structure for my simple Solidity contract complete with the contracts, deployment files, and a unit test file:
Directory Data Structure
Before we write the contract, we must design the directory data structure for our simple DApp. The Solidity language (and EVM) will impact your data structure design because the language data types are limited (i.e. integers, bytes, address, arrays, maps, and structs). Forget using your favorite relational database tool — these limitations were my first challenge to writing the app. EVM data management and storage is one concept that a DApp developer will need to master. I suggest reading the Ethereum Application Binary Interface (ABI) document for starters.
Working within the given EVM constraints, the data stored on the blockchain is logically structured like the following JSON representation:
Show Me the Code
The following is a listing of the Solidity smart contract that was created to support the new distributed payment directory:
A call is a local invocation of a contract function that doesn’t broadcast anything to the other blockchain nodes. It is essentially a read-only operation that doesn’t consume any Ether and discards all state changes when complete. From a client’s perspective, function calls are synchronous and return immediately. The Solidity __constant __keyword is used to denote read-only functions, as seen in the code above. The web3.eth.call API is used to call functions.
Transaction calls can change the state of the blockchain. They are broadcast to the network, processed by the miners, and the operation results are published to the blockchain if they are valid. Because they require work by the miners and run the risk of rejection or running out of gas, they are asynchronous calls that will only return a transaction ID. The transaction will roll back the state of the blockchain if an exception is thrown by the contract during execution. The web3.eth.sendTransaction API is used to make function calls that result in a transaction.
Because transactions are asynchronous, the client must register a callback that listens for events, and the contract writer must generate an event within the function to broadcast the result. Events are also written as part of the transaction receipts and are stored alongside the blockchain as historical data. Events (or Logs) are not part of the blockchain and are not included in the consensus process, but they are written to each node and retrievable by clients.
Testing the Contract
The easiest way I found to test a Solidity contract is using the browser-solidity web site. This is a web-based application that allows you to upload your contract, compile it, and manually interact with it by executing contract functions. It also displays all the events that are generated by the contract. You can also see detailed EVM runtime bytecode and the assembly language generated by compiling the contract. Looking at these details gave me flashbacks of the 8080-assembly language class that I took and reminded me of how thankful I am for higher-level programming languages!
The browser-solidity screenshot below shows the AliasDirectoryContract Solidity contract loaded and compiled along with the results of several function calls. This is one tool I highly recommend playing with to get a feel for what is going on under the hood.
Contract Unit Tests
Debugging your smart contract using browser-solidity is great, but as a professional software engineer, I expect developers to write repeatable unit tests, and I am not exempt. We will write a unit test that exercises the major functionality of the contract. The following is a listing of AliasDirectoryTest.js, a Mocha-based unit test file with Chai assertions.
Now that we have a unit test, we use the truffle test command to run it. Here is the output from our first attempt:
D’oh! This is an exception. It looks like the unit test is attempting to connect to an Ethereum client. We didn’t have to do anything special when using browser-solidity. How do you run unit tests without deploying the contract to a blockchain EVM? Truffle will deploy the contract for you, but we need an Ethereum blockchain client to deploy it to.
Once again, the development community solved this problem for us by writing testrpc, a Node-based application that simulates a full Ethereum client. All you need to do is fire up testrpc in one terminal window and run the unit tests in the other window. When you start testrpc, it will generate 10 accounts and their associated private keys for testing. The following shows the results of testrpc waiting for interactions:
Now we can try to run the truffle test command again. The command will compile all contracts in the build tree, deploy them to the client, and run the tests. The testrpc screen will scroll with output while the test is running. Finally, the test is done! The output is shown below:
Don’t Run Out of Gas
Previously, I casually threw out the concept of a transaction function “running out of gas”. What is that all about? I don’t intend to dive deeply into it here, but gas is essentially the amount of Ether — the Ethereum currency — that it costs to mine the result of the transaction. Because Ethereum uses a Proof-of-Work (POW) algorithm to reach consensus for each new block in the chain, you must pay the “miner” who finds the solution first for his hard work each time a transaction occurs. After all, the miner has bills to pay, too! The short of it is, each transaction submitted to the blockchain will cost you gas money (Ether). If you write sloppy, inefficient code, then it will cost you even more of your hard-earned gas money. We won’t worry about how you acquire Ether now — that will be covered in the next post.
If you want to learn more about POW and Proof-of-Stake (POS) mining and how Ethereum is planning two switch from POW to POS, this link is a great resource.
That’s a Wrap
A lot of mileage was covered in this blog post, so I will stop here. What we still need to do is write a client that interacts with the contract to build a simple directory, work to earn some gas money, and finally deploy the contract to a real Blockchain network. Until then, I will see if I can earn enough Ether to fund the journey.