Enterprise Blockchain Protocols: A Technical Analysis of Ethereum vs Fabric vs Corda
In the past 18 months since the beginning of 2018, enterprise blockchain adoption has been progressing steadily. Companies and governments alike are all trying to use this technology to solve some of the most difficult problems in the world of transactions. Businesses and regulations have strong requirements on identities and permissioning, which tend to lead them towards a permissioned over a permissionless (a.k.a public) blockchain protocol (to learn more about public vs private / permissioned vs permissionless, read this blog).
For these permissioned chains, three blockchain protocols have emerged as the top choices: Hyperledger Fabric, Enterprise Ethereum and R3 Corda. Both Fabric and Enterprise Ethereum are general purpose tools for any industry, while Corda is custom-designed for the financial industry. Each protocol option has a very different lineage and design focus, and all three have seen major adoptions by serious businesses and governments running on production-quality systems today.
In full disclosure, I have personally worked on two of them: as a Fabric committer responsible for the development of node.js SDK and node.js Chaincode engine and API library, and as an active contributor to the Quorum (one of the Enterprise Ethereum implementations) code base, as well as for the Enterprise Ethereum Alliance (EEA Technical Specification versions 2.0, 3.0 and 4.0.). This blog attempts to compare these top three widely applicable protocol options without making judgement on which one is better.
At a high level, the differences between Ethereum vs Fabric protocols can be summarized as follows:
|Node Permissioning||Smart contract based rules, with file-based per-node rules as local overrides.||Configurable on node, channel and consortium levels.||Trusted network map service complemented by file-based configurations on each node. Corda networks are partitioned into compatibility zones that are governed by separate Certificate Authorities.|
|Identity||Public keys – distributed, and interoperable between Ethereum based chains. Coupled to PKI via proofs.||Based on PKI with native organizational identity. Organizational identity rather than individual identities used throughout in consensus, and permissioning.||Based on PKI with both individual and organizational identity.|
|Cryptography||secp256k1||Pluggable (ECDSA with secp256r1 and secp384r1 built-in).||ed25519
RSA (3072bit) PKCS#1
|Transaction Consensus||Order -> Execute/Validate||Execute -> Order -> Validate||Execute/Validate -> Order/Notarize|
|Application Responsibility||Sending signed transactions to one node in the network.||Coordinating directly with all other participants to obtain endorsement, managing optimistic concurrency locking on state, signature, and submission.||CorDapps use the flow framework to coordinate with transaction counter-parties to negotiate proposed updates, obtain signatures, and to finalize with the notary service.|
|Applied Consensus Algorithms||Proof-of-Authority (BFT).
Raft (CFT with trusted leader).
Istanbul BFT (BFT with deterministic leader rotation).
|Kafka/Zab (CFT with trusted leader).
Raft (CFT with trusted leader).
|Raft (CFT with trusted leader)
|Smart Contract Engine||EVM, in-process sandbox||Docker isolation||Deterministic JVM|
|Smart Contract Languages||DSL (Solidity, Serpent), guaranteed deterministic.||Full languages (Go, Node.js, Java), non-determinism is tolerated.||Java, Kotlin, deterministic by using recommended libraries|
|Smart Contract Lifecycle||Immutable. Easy to deploy. Stored on-chain.||Requires elaborate process to deploy/change. Stored off-chain.||Requires node-level administrative operations to deploy/update. Stored off-chain.
Ongoing work to split consensus-critical code vs. non-consensus-critical code for different storage strategy (on-chain vs. off-chain respectively)
|Smart Contract Upgrade||Programming patterns to extend/migrate code & data.||Replacing off-chain code via administrative procedure and upgrade transactions.||Contracts with hash-based constraints are explicitly upgraded via node-level administrative procedures and coordinated flow to authorize and upgrade.
Contracts with signature constraints automatically allow new versions to execute, as long as signed according to the constraints and the hash matches.
|Tokenization of Assets||Native feature
Many token standards: ERC20/ERC721/ERC777 etc.
|Possible with custom solution.||Possible with custom solution.
Corda Token SDK makes it easier to build.
|Multi-chains||Each chain is unique, and requires separate node runtimes (min or 3 or 4 depending on consensus).||Native feature (channels) with shared peer runtime, and shared orderer. Built-in governance for creating side-chains with isolated state.||No concept of a chain (shared ledger). Transactions always explicitly target specific nodes. States are scoped to the designated notary which can be retargeted to a different notary.|
|Private Transactions||Public hash represents input.||Public hash represents input and private end state.||Inherently all transactions are private. The entire transaction is visible to a validating notary.|
|Community of Contributors
(as of writing)
|Fabric: 185||Corda: 146|
Origin and Lineage
Understanding how Enterprise Ethereum clients, Hyperledger Fabric and R3 Corda protocols came about is not an academic exercise; it will help explain some of the major design and functional differences between them.
Similar to how a strong enterprise community grew around Java driven by the J2EE specification, the Enterprise Ethereum Alliance (EEA) is following a spec driven approach. This approach fosters interop, while allowing multiple innovators to work independently on solutions to Enterprise requirements. There are four major Enterprise Ethereum implementations active in the enterprise scene. Three of them are modified from a public Ethereum client, with a fourth developed from scratch. All implementations are compatible to the formal Ethereum specification otherwise known as “the yellow paper”, and all have interesting and unique extensions, such as zero-knowledge proofs and modular architectures.
|EE Client||Modified From||Developer||Open Source License|
|Besu||New implementation in Java||PegaSys||Apache 2.0|
This lineage allows the Enterprise Ethereum clients to inherit the relevant skills and knowledge base in the large Ethereum developers community for developing enterprise solutions. Not only the JSON RPC APIs are familiar to the application developers, but also the smart contract language Solidity can be used with 100% fidelity. They also inherited Ethereum’s hallmark developer friendliness with ease-of-use and a ton of developer tools being widely available.
At the same time, almost all of the built-in features designed to guard the client from the most cunning hackers in the public blockchain network are also inherited wholesale. This is mostly a positive, because enterprises always welcome battle-tested design and implementation.
Besides tracing their lineage back to the public ethereum blockchain, the ongoing development of the enterprise ethereum implementations are also heavily influenced by the EEA standard body. With 600 member organizations spanning a wide range of industries, technology companies and startups, the standard body is well positioned to link protocol designs to real customer requirements. EEA takes the philosophy of being “specification led”, emphasizing cross-implementation interoperability as the goal of all design and architectural efforts.
With the first line of code written in the summer of 2015, Hyperledger Fabric was designed with enterprise usage in mind. The Linux Foundation launched the Hyperledger charter in December 2015 and IBM contributed its open blockchain code base to give birth to Hyperledger Fabric shortly after. Fabric enjoys wide open source participation from technology companies, consulting firms and startups in multiple countries. Developers and researchers from IBM are still the leading sources of code contribution, design and architecture.
The Hyperledger community is an umbrella organization that includes other code bases such as Sawtooth driven by Intel, Iroha by Soramitsu, Indy by Evernym, and even an Ethereum implementation called Burrow by Monax, plus a number of tools projects for various other concerns such as cross-chain interoperability, ops, development toolchain and crypto modules.
The enterprise-first philosophy results in Fabric’s robust enterprise security features and built-in consortium governance. This also means that getting started is significantly more involved compared to Enterprise Ethereum.
Corda started first as a closed-source project within R3, which is a consortium invested by financial companies, dedicated to developing DLT (Decentralized Ledger Technology) for the financial industry. It was later open sourced in github.com but without a non-profit governing body like the Linux Foundation or Ethereum Foundation. Committership are held by R3 employees only. Corda architecture design is heavily influenced by requirements from the financial industry, mainly privacy and regulation compliance. Key aspects include using a UTXO (Unspent Transaction Output) transaction model, and all transactions involving only the counterparties making them inherently private (though the notary service nodes can still see the full transaction details).
All blockchain systems need a consensus mechanism to ensure all nodes have the same view of the transactions input and order. Almost all existing protocols utilize consensus algorithms designed around the “order-and-execute” architecture. First all nodes agree on the transactions order inside a block, then the transactions are independently executed by each node to calculate the resulting state.
Ethereum is built on such a consensus model. A critical part of the “order-and-execute” model is that every transaction execution must be deterministic, meaning it always yields the same result given the same input and the same logic. At the same time, Ethereum’s smart contract engine, Ethereum Virtual Machine (EVM), gives developers full logic programming capabilities a.k.a being Turing Complete. These two seemingly opposing goals are achieved by removing non-deterministic language features such as file systems, network IO, clocks, floating point arithmetic etc. The result is a new domain specific language called Solidity.
Fabric took a completely different approach by tolerating, instead of eliminating, non-determinism in its consensus model. Offering full languages for smart contracts is a design principle Fabric holds true since the beginning. As of this writing, Fabric Chaincodes can be written in three full language runtimes: Golang, Node.js and Java. This is made possible by adopting the unique execute-order-validate consensus design, so that the blockchain system can endure bad transactions caused by non-deterministic Chaincode while developers continue to perfect the logic and implementation.
Details of the design is beyond the scope of this particular blog. You can refer to the comprehensive documentation on the Hyperledger Fabric docs site for the full details.
Corda consensus design is very similar to Fabric. First the nodes involved in the transaction coordinate among them to process the transaction by executing the target contract and signing the execution result. Once the required signatures are collected, the initiator node is responsible for sending the transaction to the notary service for consensus signature. The notary service maintains a full history of all the transactions that have been submitted and is able to determine if a double spending situation is happening. Once the notary service approves the transaction and signs of on the proposed result, the transaction is finalized and committed by all the parties. This makes it effectively the same execute-order-validate design that Fabric follows.
|Transaction Execution||Ordering (double-spend detection)|
|Ethereum||Ethereum Node (all nodes)||Ethereum Node (block proposer)|
Multiversion Concurrency Control (MVCC) and Its Implications
It’s worth pointing out, that the “execute first and order next” design implies that some kind of concurrency version control is necessary, otherwise when multiple transactions are trying to modify the same state value in parallel, the later one will overwrite the earlier one and wipe out the state transfer from the earlier transaction, instead of building on the result of the earlier transaction. Fabric employs a multiversion concurrency control (MVCC) technique borrowed from database design. Under the cover, the chaincode engine keeps track of what state values are being viewed (in readset) and updated (in writeset) when the smart contract is executed. During the validation phase, where each transaction contained inside a block is validated and state transfer is applied, if a transaction’s state value versions in its readset do not match the current versions, typically because they have been updated by an earlier transaction in the block, then the transaction is marked as invalid.
This is more than a subtlety. The implication is that if a series of transactions need to modify the same state value, they must be regulated such that no more than one transaction lands inside a single block. Otherwise the application will observe a lot of invalid transactions due to concurrent modifications. In the Fabric community, we have seen a rather significant cognitive barrier around this point among the application developers.
Techniques exist to program around this limitation, such as utilizing the composite key capability to assemble unique keys for each transaction while having the ability to group together keys targeting the same underlying state variable. The high-throughput sample application demonstrates how this can be done. Note, though, that not all scenarios can take advantage of this technique.
Even though Corda is built on the same “execute first and order next” design principle, its UTXO based model intrinsically guarantees that each input is unique. If any two transactions attempt to use the same input, a double spending situation is detected and the later transaction will be rejected, because the input will have already been consumed by the earlier transaction.
Ethereum invented the “Account State” transaction model, which got adopted by Fabric as well. The smart contracts maintain a world state that is scoped to that smart contract and each transaction can update or query the latest values.
There are important distinctions in the state management between Ethereum and Fabric, though. Each Ethereum smart contract is given an account by the network after deployment and can hold balances in Ether or tokens. An ethereum smart contract acts very much like a user account with a private key, which is called “Externally Owned Account,” except that smart contracts do not hold private keys, for the obvious reason, and can not sign transactions. But when a smart contract calls another smart contract, the call assumes the calling smart contract’s identity, which allows the downstream contracts to enforce access controls just like with external accounts.
This design is extremely useful in situations where an “interest-neutral” or “decentralized” third party is needed to carry out a multi-step business transaction. Such a third party is typically called an “escrow.” An Ethereum smart contract can easily be trusted as an escrow due to the attribute described above.
Fabric smart contracts, called “Chaincodes,” on the other hand are completely free of identities. A chaincode can also call another chaincode, but the transaction identity is always kept constant as the transaction signer who submitted the transaction throughout the calling chain. On a Fabric network, setting up an escrow account therefore involves adding an external party. As a result, the external account responsible for the escrow must prove its neutrality to the rest of the participants.
Corda transactions work very differently. First of all, they are based on UTXO instead of account state model. This in theory should make it more friendly to concurrent processing, because each transaction is supposed to use unique inputs. This should work as expected with fungible assets (cash, bond, etc.) which can be easily split into multiple parts so that each can be consumed in separate transactions being processed in parallel. But for non-fungible assets, which can not be split, any updates can only be performed one transaction at a time. If more than one transaction attempt to modify the same non-fungible asset, then it constitutes double spend and the later transaction, as ordered by the notary service, will be rejected.
In addition, almost all Corda transactions are about collecting multiple signatures in order to fully authorize the state transfer. Multi-party signing authorization scheme with Ethereum or Fabric would require either the applications doing the coordination to collect signatures, or submitting multiple transactions each from a different signatory. Corda transactions on the other hand is natively built on the concept of signature collection and coordination, using “flows”.
Image Source: Corda Key Concept – Flows
Both Enterprise Ethereum, such as Quorum, and Fabric support privacy with private transactions, where transactions are sent only to a subset of nodes and kept hidden from the rest. They are both built on a similar design, by using direct peer-to-peer communication to distribute private payloads and using a hash to record the proof of the transaction in the public ledger. Details of the design can be seen at Quorum github and Fabric documentation.
There are some subtle but important differences.
Quorum always encrypts the private payload at the node receiving the private transaction from the client application, before sending it to other nodes designated to participate in the transaction. This is accomplished by first generating a one-time symmetric encryption key and then encrypting it using the target node’s public key. Fabric on the other hand leaves for the client application to decide whether the private data in the “transient data field” should be encrypted or not. If encrypted, then the client application is responsible for distributing the decryption key to the endorsing peers.
The hash also represents different content. In Quorum, because execution is done later, the hash can only represent the encrypted input. This means if the nodes do not agree on the resulting private state after execution, there is no way to discover that.
In Fabric on the other hand, the private state is calculated during the endorsement phase by the peers execution the private transaction, and the resulting private state is represented by the hash, along with the input. As a result, the consistent hash on all the nodes after consensus guarantees that the participating nodes of the private transactions always agree on private states.
Fabric also offers complete data isolation as another privacy technique, with the concept of “Channels.” This is not to be confused with state channels in Ethereum. Fabric channels can be thought of as separate blockchains, because each channel maintains its completely separate instance of a ledger, shared among the participating nodes of that channel. Before the introduction of the private data collection in release 1.4, channel is the only way to achieve privacy on Fabric. If a consortium is mainly concerned with bi-lateral transactions, as is the case with most financial instruments, the number of channels get quite large: O(N^2) with N being the number of participants in the consortium.
Corda is entirely built on the philosophy that all transactions are “private”. In other words transactions are only sent to the specific counter-parties involved in the specific real-world scenario. On the other hand, there must be a neutral 3rd party that can act as witness that the transaction has happened correctly, especially in terms of order relative to each other and free of double-spend. That is the role of the notary service. In order for the notary service to perform its function, they must maintain the entire history of the transactions around the asset in question and have visibility to the content of each transaction under the scrutiny.
The notary service described above is called validating notary. It is essentially a counter-party in all transactions, with full visibility to the transaction details. Corda also supports non-validating notaries for privacy purposes. Non-validating notaries only checks for double-spending without validating the transaction input themselves. Transaction details such as signer identities are hidden from non-validating notaries. This provides similar privacy support as the design adopted by Quorum (as well as Hyperledger Besu which supports the same private transaction design) and Fabric, where only the hash for the private transaction is shared with the consensus service.
Smart Contract Management
Ethereum’s smart contracts are immutable. After deployment, they can’t be upgraded. This is by design because in the public blockchain it would not be a good idea to allow the logic behind a contract to be changed after public investment with ICOs.
Upgrading a smart contract in Ethereum requires one of two approaches:
- Upgradable Contracts through a Proxy Contract – where the original contract code is written with migration in mind. So that all of the logic and state is upgradable, without changing the interface or address.
- Contract Migration – deploying a new contract, which gets assigned a new address, and copying over the existing state from the old version.
Both are well documented and practiced with code libraries and examples in the community.
Ethereum also allows anybody to deploy smart contracts. This again can be attributed to Ethereum’s public blockchain lineage that strives to achieve a decentralized operating model by encouraging open participation.
Ethereum contract code can be re-used. Each deployment of the same contract code results in a different instance and assigned a different address.
Fabric manages Chaincode with a very different philosophy. It requires all I’s dotted and T’s crossed. Deploying a Chaincode is a two-step process. Because the executable binary for the Chaincode does not actually live on the ledger, unlike Ethereum, they must first be installed on every endorsing peer selected to support it. Next the whole channel must agree on the exact version of the Chaincode to execute and the endorsement policy for transactions, by a step called “Chaincode instantiation”. The user submitting the instantiation transaction must pass the validation against the “instantiation policy” to ensure they are approved to do so according to the predetermined rules when the consortium was established.
Fabric chaincodes are upgradeable. They get assigned a name and version. When upgrading, a new version will be assigned and all existing states are inherited automatically.
Fabric chaincode can also be re-used. The same chaincode, written in any of the chaincode languages (Go, node.js, Java), can be installed and instantiated under different names.
Corda contracts are Java classes loaded into a JVM to execute. Corda contracts are compiled, packaged as jars and signed, then installed on each counter-party’s node. Corda transactions, via the contained state objects, always specify a hash pointing to the installed contract to guarantee consistent processing.
Corda contracts versioning and upgrade is natively supported as in Fabric, with more flexibility in the upgrade flow and policy threshold. Upgrading a contract with only hash constraint requires a special flow that collects authorizations from counter-parties to attach a different contract hash, and then migrate the state objects over to the new version. Upgrading a contract with signature constraint is much easier because the initiator only needs to attach the hash pointing to the new version in a transaction, then as long as the new version is signed properly according to the signature policy it will be used to process the transaction.
Corda contracts are referenced by their fully qualified class name and the hash of the containing JAR. Code re-use is achieved by having different state objects reference the same contract by the class name and hash.
Digital asset tokenization is a recent popular trend in the enterprise blockchain space; in fact, the term “token” is no longer just a concept associated with public chain based cryptocurrencies and ICOs (Initial Coin Offering). Due to their well defined and easily understood attributes and lifecycle, tokens make it easier to manage and exchange digital assets among parties. Recent announcements of major blockchain projects using token design, such as the JPM Coin and World Wire, are a testimony to the legitimacy of the architecture.
Tokens and their usage in permissioned blockchains is a topic that deserves a full blog of its own. I will merely cover the high level concepts and compare the support in the two protocols.
The most fundamental concept is fungibility. It can be loosely interpreted as “being exchangeable.” Currency is a fungible asset class because all U.S. dollar bills are worth exactly the same and you do not have to have any particular dollar bill to get the value. Real estate, on the other hand, is a non-fungible asset class because every house is unique. Even if the design is exactly the same, the difference in location can drastically affect the values of any two houses.
Typical features of a token include the following:
- Ownership: who owns a particular token (non-fungible) or what amount of tokens (fungible).
- Transfer: to allow the digital assets to be traded.
- Minting: for new tokens to be created for circulation.
- Burning: owners are allowed to “burn” tokens. This is used in cross-chain trades. Since tokens can not transfer across chains, they get burned in the sender’s chain and minted in the receiver’s chain.
- Custody: owners can approve of accounts to look after a portion of their tokens. In scenarios where an escrow is involved, the escrow account can be approved as a custodian by the tokens owner.
Any blockchain protocol that supports smart contracts can be used for tokens. At the end of the day, a token is a number that can be owned and transferred. So a token based solution is possible with Ethereum, Fabric and Corda. The Ethereum community has done a great deal of work to evolve token contract design in order to support various use case scenarios, from fungible to non-fungible to partially fungible token specifications. The result is a rich collection of token contracts covering a wide spectrum of real world requirements.
Ethereum has some unique advantages when it comes to tokens. As explained in the “Transaction Model” section above, smart contracts themselves can act as a mutually trusted escrow, which makes it much simpler to use Ethereum to implement use cases where token trades must be brokered by a trusted 3rd party. Indeed, most decentralized exchange services are built on this feature. It is also essential in popular techniques such as Atomic Swaps based on Hashed Timelock Contracts, a proven technique to broker token trades between different token contracts from the same blockchain or across different blockchains.
Another advantage is the wide variety of real world deployments for all types of tokens in the Ethereum community. From stable coins to CryptoKitties, companies and consumers alike have already used tokens on Ethereum for a long time, resulting in a robust technological foundation and a wealth of technical information at your disposal. High quality smart contract libraries such as OpenZeppelin make it trivial for a developer to get started.
Corda originally shipped with built-in asset types for token-like models such as cash and other types of assets. They were later split out into a more generalized tool called Tokens SDK.
Governance is the process and policy around the protocol runtime to ensure consortium member organizations have proper participation in the decision making processes.
Enterprise Ethereum clients, being born out of the world’s most famous decentralized blockchain, must superimpose a permissioning layer. The Enterprise Ethereum Alliance has made a chain-wide permissioning configuration and enforcement part of the 3.0 version of the standard specification. Various clients have implemented per-node permissioning rules as well as smart contract based governance flows. Quorum has recently released a beta version of a comprehensive permissioning and governance framework.
Fabric has permissioning governance built-in on every layer of the architecture. Operations like starting a new consortium, adding or evicting members, defining a new channel, adding and evicting participants from channels all require collecting approval signatures from the appropriate organizations. The overarching policy model is enforced throughout the system.
Fabric has two levels of permissioning and governance support: consortium and channel. The orderers manage the policies and configurations on the consortium level. Every Fabric blockchain network starts with the orderer bootstrap from a genesis block configuration that defines the organizations and consortiums. The peers manage the policies and configurations on the channel level. Modifying configurations, such as adding new member organizations to a consortium or a channel, requires collecting signatures according to the modification policy: ANY, ALL or MAJORITY of the existing members.
One common complaint of the Fabric governance design is that it’s centralized. This is rooted in the fact that until version 1.4 the orderers support only centralized ordering engines: SOLO (single-node orderer with no fault tolerance, for development mode only) and Kafka (centralized queue with crash fault tolerance consensus). The result is that practical deployment of the orderers can only be operated by a single organization.
The fact of the matter is that the Fabric architecture itself allows for decentralized orderer implementation. Indeed, with the introduction of Raft based orderer implementation in version 1.4, there is no need to pair the orderer nodes with a centralized ordering engine any longer. Each orderer node itself is a Raft peer and can participate in leader election in the event when the current leader crashed or became unreachable. This allows for a more decentralized deployment where more than a single organization can operate orderer nodes and participate in consensus and proposing blocks.
With Corda, permissioning and governance is very similar to Fabric. This should not come as a surprise given the similar lineage rooted in enterprise use cases. For a Corda node to be allowed to communicate with existing nodes, it must present signing certificates that has been signed by a trusted Certificate Authority. A trusted network map service is used as the authoritative source of permissioned certificates. Adding a new node requires a coordinated administrative procedure with the network map service used by the nodes it needs to communicate with. Unlike in Fabric, where permissioning must be set up on every node participating in a particular channel so that the Gossip style peer-to-peer communications can be carried out, Corda nodes communicate with each other only as directed by the CorDapp flow. As such, permissioning only needs to be set up between the nodes that are part of the same CorDapp. In addition, permissioning must also be set up between the nodes and the notary service designated for the assets managed by the CorDapp.
As mentioned at the beginning of the article, Enterprise Ethereum, Hyperledger Fabric and Corda have all seen adoptions by major industry leaders, governments as well as innovative startups. All three protocols have been trusted to power production quality systems that are running real business transactions. Most of the differences cited above amount to design choices, and point-in-time gaps that are being addressed. Blockchain technologies as a whole are still in the active growth phase, which makes it a very exciting time to dive in now. Choosing one over the other is likely not the best strategy at the moment. More likely than not, enterprise organizations are working with two or all three protocols in their various projects. That’s a smart thing to do. As they all enjoy vibrant developer and user communities, which is the most important factor to guarantee long-term viability of the technology, one can hardly go wrong with any.
It’s important to point out, though, that the blockchain layer is but the foundation of a comprehensive enterprise consortium solution. Numerous other concerns need to be taken into account, including deployment infrastructure (cloud, on-premise or hybrid), governance structure (benevolent dictator, fully democratic or anything in between), privacy, asset management model, and identity, just to name a few. For discussions on full-stack enterprise blockchain solution architectures and how blockchain platforms fit into the picture, review these other resources by Kaleido:
- Smart Contracts and How Do They Work
- Privacy Solutions in Enterprise Blockchains
- Kaleido Full-Stack Blockchain
[Special thanks to Richard Brown, CTO of R3, for his thorough review and feedback on Corda]