Enterprise use cases deployed in Oracle Blockchain are growing in complexity and blockchain topology is evolving to support them. Some applications use multiple chaincodes that work on separate but related ledgers, which are deployed on multiple channels. This is similar to how Microservices within a single application often deal with different databases. For example, when an application combines a service or exchange of goods and a payment for the service, these may be persisted in separate ledgers, but need to be committed atomically (either all of them successfully, or none of them). Similarly atomic updates are required when there’s a token exchange with tokens on separate channels (or even separate blockchains), so that neither party gets credited unless both parties do. With the complexity of transaction ordering and commit protocols, this hasn’t been possible in Hyperledger Fabric (HLF from here on) or other blockchains – different transactions hitting different channels are always committed independently from each other.
In order to make blockchain more suitable for complex application scenarios, Oracle worked on addressing this challenge and has provided cross-channel atomic updates based on 2-Phase Commit (2PC) model in the latest version of Oracle Blockchain Platform. In short, 2PC model consists of two phases – Prepare phase where a coordinator process attempts to prepare all the transaction's participating processes to take the necessary steps for either committing or aborting the transaction and to vote, either "Yes": commit (if the transaction participant's local portion execution has ended properly), or "No": abort (if a problem has been detected with the local portion), and the Commit phase, in which, based on voting of the participants, the coordinator decides whether to commit (only if all have voted "Yes") or abort the transaction (otherwise), and notifies the result to all the participants, which then proceed to commit the updates or roll them back (in case of abort).
The approach described here implements these concepts in HLF:
This is achieved without changing the HLF client/server API, and it supports different levels of transaction "isolation" (even if the term is used liberally in this context).
While the Two-Phase Commit (2PC from here on) transactions can be manually managed by a client application, our long-standing objective is to provide commonly useful capabilities in the OBP as built-in features whenever possible, so developers don’t need to rely on complex client logic or an external Transaction Manager. This post highlights how you can rely on REST Proxy in Oracle Blockchain Platform (OBP) to invoke multiple blockchain transactions across different channels in an atomic manner and leverage the REST Proxy as the Transaction Manager.
OBP REST Proxy exposes a new atomicTransactions endpoint which accepts multiple HLF transaction requests – typically spanning different channels, and it returns details about the success or failure of the atomic operation. As an example, suppose your blockchain network enables users to exchange marbles (reusing a popular HLF example) on channel goods, and tokens (leveraging another simple HLF example – balance transfer) on channel wallet. Now suppose that Garcia wants to sell Smith his marble1 in exchange for 50 tokens. That operation involves two distinct blockchain transactions hitting two different ledgers. HLF doesn’t provide any mechanism to force those two transactions to happen atomically, creating the risk that Garcia might not get his tokens after transferring ownership of marble1 to Smith; or that – vice versa – Smith might not get the marble even after transferring tokens to Garcia. In blockchain world, such an exchange across multiple chains, e.g., Bitcoin and Ethereum is often handled by a Hash Time-Locked Contract (HTLC) implementation that uses escrow accounts on each network and requires both users to orchestrate a number of steps.
Atomic transactions across channels are meant to solve exactly this kind of problems, but without the cost and complexity of HTLCs. Instead of thinking about the two blockchain transactions as two distinct operations, we think about them as a single atomic transaction, which consists of two operations. The API allows multiple operations to be specified in an array form, each involving separate chaincode and channel as shown below:
That’s the payload that an application can send to the atomicTransactions endpoint in OBP REST Proxy. You can easily recognize the two specific operations that the application is requesting to perform – and which must happen atomically.
If all goes well, and marble1 gets transferred to Smith, as well as 50 tokens get transferred from Smith to Garcia, the requested operation returns a response of this kind:
The response is telling us quite a few things:
What happened under the cover is that OBP REST Proxy coordinated the execution of the transaction by:
Now, let’s suppose that the same flow is executed in a context where Smith doesn’t have enough tokens to pay for Garcia’s marble. Here’s the response we will see:
This return payload tells us that:
It’s worth noticing that no compensation logic needs to be applied to the rollback operation, as the overall design of the solution simply allows us to remove the staged changes and the related locks.
The following table shows a (heavily simplified) description of the sequence of transactions corresponding to the successful/failed invocations described above:
Channel |
Chaincode |
Operation |
Arguments |
TxID |
Comment |
Successful case | |||||
Goods | obcs-marbles | transferMarble | marble1, smith, 2pc.serializable, 2pc. 259910a26006 |
fe262233 | prepare |
Wallet | obcs-example02 | pay | 50 2pc.serializable, 2pc. 259910a26006 |
9caf809c | prepare |
Goods | obcs-marbles | 2pc.commit | 2pc. 259910a26006, 2pc.prep. fe262233 |
badcb3b4 | commit |
Wallet | obcs-example02 | 2pc.commit | 2pc. 259910a26006, 2pc.prep. 9caf809c |
1594d0ab | commit |
Failed Case | |||||
Goods | obcs-marbles | transferMarble | marble1, smith, 2pc.serializable, 2pc. 259910a26006 |
fe262233 | prepare |
Wallet | obcs-example02 | pay | 50 2pc.serializable, 2pc. 259910a26006 |
… | prepare failed |
Goods | obcs-marbles | 2pc.rollback | 2pc. 259910a26006, 2pc.prep. fe262233 |
badcb3b4 | rollback |
How does all this work under the cover – at the peer level? Each phase of the 2PC Prepare/Commit protocol for each sub-transaction is handled as a normal HLF transaction with its own endorsement and commit phase:
2PC Phase |
HLF Phase |
Peer actions for each channel/chaincode |
Prepare | Endorsement |
|
Commit |
|
|
Commit | Endorsement |
|
Commit |
|
|
Rollback | Endorsement |
|
Commit |
|
In summary, these enhancements at the HLF peer level together with the associated REST proxy orchestration capabilities allow us to provide atomic update capabilities across multiple channel/chaincode operations without impacting the chaincode business logic or burdening the client application with additional complexity.
There are valid scenarios where this requirement comes up – for example, when using off-chain storage for large records or documents in concert with blockchain record to anchor the related metadata in a tamper-proof distributed ledger. Or the same example of token exchange mentioned earlier, but across Oracle blockchain and Ethereum.
The same 2PC mechanism in OBP can be leveraged but the orchestration has to move outside of the OBP REST proxy to an external Transaction Manager. There’s a well-known and widely used XA distributed transaction protocol, which uses Transaction Managers in concert with XA Resource Managers (RMs) for each data store. By implementing XA Resource Manager for OBP on top of 2PC primitives, we can bring the advantage of an XA protocol – using standard Transaction Managers (like WebLogic, JBoss, WebSphere, or Tuxedo) – to coordinate distributed transactions across OBP and a variety of other data sources which support the XA protocol.
Thanks to the 2PC protocol support described above, the latest release of OBP also provides an OBP XA Resource Manager as a Java library, which allows developers to include OBP transactions coordinated by external Transaction Managers (like WebLogic) in conjunction with transactions for other XA-compatible data sources (Oracle DB, MySQL, …) and ensure they are atomically committed (or rolled back) as a group. More to come about this in a future post, including how to include transactions for other blockchain in atomic updates.
Being able to execute multiple transactions across different blockchain channels in an atomic manner is crucial to many use cases. No blockchain implementations other than Oracle Blockchain Platform supports such use cases without the need to change existing chaincodes and/or to introduce different concepts like Hashed TimeLock Contracts (HTLC).
The underlying 2PC protocol supported by OBP allows not only to execute atomic transactions across different channels of the same blockchain network, but also across different networks and even across multiple resources (OBP and Oracle DB – for example) when exposed as an XA implementation, which can be coordinated by external transaction managers.
To try this yourself, attend the Low-Code Blockchain NFT Apps Using Blockchain App Builder and APEX [HOL4082] Hands-on Lab at Oracle CloudWorld 2022 (Las Vegas, Oct. 18-20). Afterwards, this will also be available as a self-service Oracle LiveLab at https://apexapps.oracle.com/pls/apex/dbpm/r/livelabs/home.
Previous Post
Next Post