One key difference between Hyperledger Fabric and many other blockchain platforms is the lifecycle of a transaction. In other platforms, the lifecycle of a transaction is usually this:
- Order: Transactions are added to the ledger in some order and disseminated to all peers.
- Execute: Transactions are sequentially executed (e.g. using smart contract code) on all peers.
In order for all peers to end up with the same state, transactions must always execute deterministically — i.e. the same transaction must always create the same result, no matter where or when it is executed. This requirement places strong limitations on what a smart contract can do, which is one reason why smart contracts often use a special domain-specific language. It’s generally not possible to enforce determinism in a general-purpose language (e.g. Java or Go).
In Hyperledger Fabric, the lifecycle of a transaction is different:
- Execute: Transactions are executed (using chaincode) in any order, possibly even in parallel.
- Order: When enough peers agree on the results of a transaction, it’s added to the ledger and disseminated to all peers. This step is where the transactions are first given an ordering — until transactions are added to the ledger, there’s no concept of one transaction happening before or after another.
- Validate: Each peer validates and applies the ledger’s transactions in sequence. Now that the transactions have an ordering, the peers can check whether a later transaction was invalidated by an earlier transaction. For example, this prevents one item from being sold two times (called double-spending).
The first note to make here is that there’s a separation between the execution of a transaction (Execute step) and actually updating the ledger (Validate step). This separation has useful effects:
- All peers need to update the ledger, so all peers do the Validate step. But not every peer needs to Execute the smart contract. Hyperledger Fabric uses endorsement policies to define which peers need to execute which transactions. (More details later in this post.) This means that a given chaincode (smart contract) can be kept private from peers that aren’t part of the endorsement policy.
- Transactions can be executed before they are put in order. This allows peers to execute transactions in parallel, which can improve throughput.
- In Fabric’s three-step execute-order-validate model, the results of executing chaincode for a transaction are explicitly agreed upon (according to the endorsement policy) before the transaction is added to the ledger. The two-step order-execute model uses deterministic “chaincode”, which implies that peers will agree on the result of executing a smart contract. Making agreement explicit allows Fabric to use non-deterministic chaincode, which is why you can write Fabric chaincode in Go, Java, and Node.js.
Hyperledger Fabric allows users to define policies around the execution of chaincode. These endorsement policies define which peers need to agree on the results of a transaction before it can be added to the ledger. Fabric includes a small domain-specific language for specifying endorsement policies. Example endorsement policies might be:
- Peers A, B, C, and F must all endorse transactions of type T
- A majority of peers in the channel must endorse transactions of type U
- At least 3 peers of A, B, C, D, E, F, G must endorse transactions of type V
The endorsement policy isn’t responsible for making sure the right chaincode is installed on the right peers. However, there is a similar mechanism for “endorsing” and installing chaincode packages — a topic for another post.
How Endorsement Works
So far, I’ve been using the term transaction somewhat loosely. In the order-execute model, the concepts of executing chaincode and updating the ledger are combined into one idea — transaction. In Fabric, these two concepts are separated, so the idea of transaction is split as well.
Fabric starts with a transaction proposal. It’s a bundle of information used to trigger a specific chaincode. The transaction proposal is sent to some peers for endorsement. An endorsing peer executes the chaincode, which (if it succeeds) yields an actual transaction for the ledger. The endorsing peer then signs the transaction and returns it to the proposer. This is the Execute step in execute-order-validate.
Once the creator of the proposal receives enough signatures to satisfy the endorsement policy, it can submit the transaction (and the signatures) to be added to the ledger. This is the Order step.
Hyperledger Fabric takes a novel approach to blockchain transactions. Separating the process of executing smart contracts from the process of updating the ledger makes it possible to improve transaction throughput, support more granular privacy controls, and implement more flexible and powerful smart contracts. One of the key ingredients for making this possible is a system for explicitly endorsing transactions before they are added to the ledger.
If you have thoughts or questions, please post them in the comments! I’m excited to continue providing information about Hyperledger Fabric and other blockchain technologies.