New Environments Call for New Ways of Thinking and Doing
In 2011, Marc Andreesen declared that “software is eating the world”, predicting a software revolution across all industries. As the industries transformed, so did the way we think about and interact with their relevant environments.
When software moves into new domains, the “right way” to think about how to build that software frequently changes.
In the early days of computers, software was written on punch cards and computers were a highly specialized form of equipment, costing millions of dollars. Every program was a bespoke creation, specific to the machine it was running on.
With time, the price of computers dropped inexorably even as they became more powerful, which led to a new way of thinking about software. Computers were so cheap we could think of them as commodity hardware, even though software was becoming ever more complex and valuable. We needed the ability to take code written for one computer and run it on another, a new programming paradigm known as portable code.
As the 70s came around, relational databases were introduced and the industry quickly learned that updating part of a sequence of related changes in a database could lead to all sorts of difficult problems, and we created the programming paradigm of atomic transactions. “Atomicity” just means “all or nothing”: we group a set of updates together, and they are either all applied, or none of them, to ensure that our data stays consistent. But dealing with atomic transactions inside traditional programming languages was awkward, leading to an industry standardization around a new language, SQL.
In the decade that followed, computer displays became sophisticated enough to develop interactive graphical user interfaces. Interactive communication with the user didn’t fit well with the procedural programming paradigm that worked so well in the days of “batch processing”. The same team from Xerox PARC that developed the GUI worked to refine the object-oriented programming paradigm, a natural fit for all of the new virtual user-interface “objects” like windows, icons, menus, and pointers. Object-oriented programming took over the computer industry like a storm, spawning some of the world’s most prevalent programming languages: Java, C++, and C#.
When the web era came along, developers wanted users to be able to download programs and execute them quickly on the end user’s computer, regardless of what kind of hardware the browser was using. Known as client side scripting, this was a fundamentally new way of running software, leading to a new wave of applications bringing rich functionality to the web. Keeping this execution environment efficient and at the same time safe demanded a new language: the now ubiquitous JavaScript.
When we first start building programs for a new domain, we usually start by using the old programming paradigms, because we know them and understand them. But as time goes on, we tend to find that there’s a better way to model the common problems within that new domain. This often results in completely new programming paradigms, and new programming paradigms usually warrant the creation of new programming languages.
What’s new in the blockchain domain?
Blockchains represent a new kind of software domain, with autonomous software running on decentralized systems providing open access to all. Given that previous domains have given rise to new programming paradigms, it’s worth asking: What is new in the blockchain domain that might demand a new programming paradigm?
There are many different kinds of blockchains, from Bitcoin to Turning-complete smart contract platforms like Ethereum. However, whatever shape and size they take, there are two key features that are ever-present in this new domain: scarce assets and securely controlling access to those assets.
Not all of these assets are purely financial in nature. For example, CryptoKitties aren’t likely to be listed on a stock exchange, but what makes them interesting and valuable is the fact that the specific attributes of each Kitty is carefully controlled by a public and well-understood smart contract. If the scarcity and individuality of each CryptoKitty wasn’t protected by the blockchain, they would have no tradable value and it would be a much less interesting ecosystem.
Of course, it's not useful to have a notion of scarce assets if you're not able to control who can access those assets. If anyone could breed your CryptoKitty, the concept of ownership is meaningless. The ability to control access to these scarce assets is fundamental to a blockchain’s utility.
Using Data Structures for Scarce Assets
Of course, representing scarce assets within digital systems wasn’t invented with blockchain! We’ve been representing value inside computer systems since the 1950s. All previous digital representations of scarce assets existed within a walled garden of trusted institutions, but it’s worth looking at how the existing programming paradigms dealt with scarce assets, using standard data structures.
Data structures are the foundational building block of modern software design. Instead of treating the computer’s memory and storage as a simple bag of bytes, we can define specific structures that map onto real-world concepts. Much of the history of increased programmer productivity has been the story of making data structures easier to use: easier to create, easier to copy, easier to cleanup when no longer needed (i.e. deleted or destroyed).
That is fantastic for solving most programming problems, but it actually can cause problems when dealing with scarce assets not residing within a trusted institution’s data vault. After all, public blockchains are decentralized and trustless by design. When dealing with valuable assets on a blockchain accessible by anyone, we want those same operations to be carefully guarded, with more thoughtfulness behind them than just data structure updates.
In Solidity and WASM, “scarce resources” are just data structures!
With only one tool in their toolbelt, the onus of securing scarcity falls solely on the smart contract engineers… at no small cost. As an example, just about half of the code in CryptoKitties is dedicated to managing Kitty scarcity and access control.
Code like that needs to be repeated for every project; Solidity programmers need to put significant effort into making sure access control is air tight and that the assets cannot be fraudulently created or accidentally destroyed.
One possible solution to this problem was noted by academic researchers as far back as 2015: adopting “Linear Types” into the blockchain context. A team at CMU, led by Michael Coblenz, went so far as to define a new smart contract language called Obsidian that incorporates linear types.
Linear Types are a more restrictive form of data structure that are used in languages like Rust to improve memory efficiency and prevent certain kinds of programming errors. The exact details aren’t important, but what’s important is that they get a lot closer to the properties necessary for scarce assets.
The match still isn’t perfect. Linear Types guard against accidental destruction, but they still allow for easy creation (what you might call counterfeiting when dealing with scarce assets!), and there are some subtle technical differences between “uniquely referenced” and “uncopyable”. (Although, the same mechanisms used to track unique references can be applied to protecting against copying, so there are many existing methodologies to achieve that.)
Linear Types get us tantalizingly close, but we need to take it one step further and introduce “Resources”.
Resources are Linear Types with Controlled Creation and Runtime Support
Resources are a perfect match for managing scarce assets; they have carefully controlled creation, they are uncopyable and unforgeable, and their destruction must be explicit and deliberate.
They are a very restricted kind of data structure, derived from Linear Types, with three rigorously enforced rules:
- Each Resource exists in exactly one place at any given time. Resources can’t be duplicated or accidentally deleted, although they can be moved.
- Ownership of a Resource is defined by where it is stored. There is no central ledger that needs to be consulted to determine ownership.
- Access to methods on a Resource is limited to the owner. For example, only the owner of a CryptoKitty can breed it in order to give birth to new offspring.
Resources dramatically simplify the complexity of programming scarce assets. Including Resources in the programming language allows the programmer to simply mark specific elements of their program as Resources, and the language itself will securely and automatically enforce the common functionality of scarce assets: single ownership, controlled creation, unforgeability, and deliberate destruction.
Controlling Access: Capability-Based Security
While Resources neatly solve the problem of scarce assets, this article started by noting two problems common to blockchains that aren’t well solved by existing programming paradigms: scarce assets and controlling access.
Fortunately, there is an access control mechanism that has been studied extensively since the 1980s called Capability-Based Security (CBS). CBS controls access to secure services by using a “what you have” model of security (akin to a physical key card), in contrast to the “who you are” model of security commonly called “Access Control Lists” or ACL (akin to having your name on a guest list).
CBS systems have been shown to be easier to audit, allow more flexible access control patterns, and bypass some common security escalation problems inherent in ACLs. On the other hand, ACLs are easier to implement and can be easily built on top of systems without in-built security features, which is why ACLs are more common.
Fortunately, the key building block required to implement CBS security is the existence of an unforgeable object with single ownership, controlled creation, and deliberate destruction. That’s right! We can create “virtual key cards” as Resources – the same tool we use to represent scarce digital assets – and use them to manage access control in a more flexible and natural way than ACLs (what many smart contracts languages have used to-date).
The New Paradigm: Resource-Oriented Programming
We call this new paradigm Resource-Oriented Programming, and it’s a natural fit for blockchains. You might be surprised to learn that there are already two different smart contract programming languages that implement it.
The Libra project released the Move language last year. Move is a low-level, highly efficient language with a direct bytecode representation and performant runtime. As a low-level language, the syntax is designed more for machines than people, and is largely intended as an intermediary representation.
The Flow team announced Cadence earlier this year. Cadence is a high-level, interpreted language, with an ergonomic syntax making it easy to learn, easy to write, and easy to audit.
These two projects go together like peanut butter and jelly! The teams behind these projects are working together to make the perfect smart contract sandwich out of the creamy, smooth performance of the MoveVM with the tangy, sweet syntax of Cadence. The result promises to create smart contracts that are faster, safer, and more powerful.
If you are interested in learning more about Cadence, we have a detailed documentation section here, or join us on our Discord server.