Walter Montes
Aug 20 · 7 min read

Originally posted in Hackernoon: https://hackernoon.com/oracles-for-hyperledger-fabric-with-convector-suite-ay2u130w9

Oracles for Hyperledger Fabric with Convector Suite

How to gather data from the real-world (i.e.: APIs) and boost your smart contracts built with Convector Suite.

Hello all. Walter from WorldSibu here. Our open source community grows every day and as it matures along with the framework we can move to more complex topics.

This topic was recently discussed in the Discord chat so I decided to create an example of how to work with oracles in Convector Suite (not to be confused with “Oracle” the company 🧐).

This blog post is to help you understand what oracles are, how to integrate them, and get a real example up and running. I know how hard it is to find real examples of how to do blockchain in the enterprise — we try a lot to create repos like this one to guide developers in our Github.

I will be using Convector Smart Contracts, Hurley, NestJS, mockable.io, and of course, Hyperledger Fabric 1.4. Since oracles can be confusing at first I will try to explain and iterate in the data flow through multiple conceptual and technical diagrams.

No time to read? Go download the repo here!

When are oracles necessary

Oracles are the means by which a smart contract can access data from off the chain. A smart contract can’t rely on external data for computing — meaning that it needs deterministic data to compute and apply transactions to the ledger.

Consider the following scenario of what could happen if the smart contract could access an external resource like an API:

  1. Bank A, Bank B, and Bank C get into a multi-party workflow.
  2. A transaction depends on one value from the Central Bank.
  3. Bank A sends the transaction to Smart Contract 1.
  4. Bank A, Bank B, and Bank C run it. In a blockchain typically every member that will endorse a transaction need to emulate it locally on their peer.
  5. Smart Contract 1 calls an external API from the Central Bank from every member of the network.
  6. Bank 1 gets “10” as the response.
  7. Bank 2 gets “10” as the response.
  8. Bank 3 gets “11” as the response.
  9. The transaction gets rejected. 🙅‍♂️

This may happen because external resources are not deterministic. They may change from time to time. Failures, changes, attacks, all can affect the computing of a smart contract.

However, if Central Bank was in the blockchain:

  1. They add a record called “Value=10” to the ledger beforehand.
  2. Smart Contract 1 references that value in the ledger.
  3. Bank 1, Bank 2, and Bank 3 run the transaction.
  4. Everybody gets the same result. ✅

This looks nice, but data needs to be put before its needed. What about on-demand off-chain data? That’s where an oracle is helpful.

An oracle allows for requesting external resources, save them, and compute based on that data. An oracle is more than just code — it’s a kind of trusted entity that everybody relies upon to “reflect” real-life data into the chain keeping the track of the requested resource and making the computing deterministic.

The transaction computes and requests the external resource through an event. The oracle computes the requests, gets the data, and “restarts” the transaction by calling the function __callback() inside of the original smart contract.

In a nutshell is like saying… “we start this transaction but need this value to finalize it. Hey Mr. oracle look and find the external resource for us and then store it in the blockchain and let us know to complete the transaction”.

We will look further into the flow later in the post.

Some common data that may be required from the outside includes:

  • Weather data.
  • IoT events.
  • Centralized databases.
  • News.
  • Payment proofs.

A typical flow includes 2 main steps:

Step 1: Initiate the transaction and request the external resource.

Step 2: Get the response from the outside world and continue the transaction.

You would need these main components:

  • Your smart contract.
  • An oracle daemon (external web server listening to requests from the chain).
  • Your external resource (API for instance).

Initiate the transaction and request the external resource.

  1. Send the transaction that needs external data to complete.
  2. Requests data from the outside through an event to the oracle daemon but won’t wait for it.
  3. Oracle daemon asynchronously requests for data (no more involvement for step 1).
  4. The Smart Contract responds to the requesting user with a successful status if the consensus is reached.

Get the response from the outside world and continue the transaction.

  1. External API responds with an external resource.
  2. Sometimes oracles may handle retry and failure of requests.
  3. The oracle daemon triggers a request to the function _callback() in Smart Contract 1.
  4. The function triggers the smart contract to continue the transaction based on the input data.
  5. The user gets an async notification of finality (optional).

Show me the code!

Download the source code here:

There are a few key concepts:

  • The blockchain (Hyperledger Fabric network created with Hurley).
  • Your smart contract (carinsurance in Convector).
  • The oracle daemon (conv-oracle in Nestjs).
  • Your external resource (mockable.io).

The logic of the code is:

  • You create() a car but the .insuranceLevel property will be set by the oracle by querying an external web service.
  • Once accepted the transaction, an event will be launched for the oracle daemon (nestjs) to fetch the data.
  • The oracle daemon is actively listening for events from the chaincode and once it gets a request to query data it goes to mockable.io to get a response and trigger __callback() .
  • The field .insuranceLevel will be set with the data returned by the API. Also, the value dateOracleResponse will be set to log when the oracle returned data.

Our model is pretty simple:

And our controller looks like this:

A few things to notice:

  • In the function create we trigger an event this.tx.stub.setEvent . That event is awaited by the oracle daemon (conv-oracle).
  • The callback function will query for cars waiting for some identity to submit a transaction with the value for insuranceLevel .

Let’s explore the actual flow a bit more in detail:

To run the project first make sure to meet Hyperledger Fabric pre-requisites.

Then, you will need a mockable.io API running — https://www.mockable.io

In there you just need to follow the tutorial and configure it like this:

Notice the Verb in POST and the Path with bankapi.

Then just make sure to get it up:

Click on “stopped” — yeah the UX is weird, you click “stopped” to get it up.

Copy the url in the field Path including the bankapi piece. This will emulate our external API that the oracle daemon will call.

Add a new file in ./packages/conv-oracle/src/.env with the following content:

EXTERNAL_URL=<full-url>

This will tell the server where to fetch the data.

The first transaction will take a few seconds to instantiate the smart contract in the second organization.

Congratulations! You ran your first oracle with Hyperledger Fabric thanks to Convector! 🎊

Let’s explore the data — go in your browser to http://localhost:5084/_utils/#database/ch1_carinsurance/1

You will see something like:

Fields dateOracleResponse and insuranceLevel were set by the Oracle from the API.

Try some things to prove that it’s not cheating, turn off the oracle daemon (just type control+c) in the tab running the server.

Send another transaction:

hurl invoke carinsurance carinsurance_create “2” “volk” “1199”

And explore the results: http://localhost:5084/_utils/#database/ch1_carinsurance/2

Oracles are a great tool to have at your disposal — we make use of Convector’s ability to use Hyperledger Fabric’s events and with this bootstrapped nestjs oracle daemon you can start doing some neat things!

I hope to see you around in the Discord community! Hundreds of devs helping each other and learning together!

What to do next

Just like blockchain infrastructure, oracle’s infrastructure is not trivial — in fact, that’s why we created Forma to solve the infrastructure pains without cutting out the decentralized benefits of a blockchain network. So here are my recommendations to what to focus on when creating oracles:

  • Create mechanisms for dynamic queries and dynamic models (responses).
  • Implement ways to encrypt queries and responses.
  • Secure the oracle identity and verify it in the blockchain (__callback() function) just like we advise in the identity-pattern here (this will protect you from hijacking since a request to get data is made through an event there’s no response so the only space for somebody to get in the middle is when the oracle queries the external API and then responds).
  • Create high availability for the oracle daemon, authentication and authorization, black and white-lists, network security, and queues to process requests and avoid duplication.
  • Log everything that happens and every oracle response.

Just to mention a few. Oracles are critical components of blockchain networks and as such they should be treated carefully.

Conclusion

What do you think? Real-life data is necessary for real-life blockchains. We love exposing our experience and building along with the community.

Covalent

A unified development platform to create and deploy enterprise smart contract systems.

Thanks to Diego Barahona

Walter Montes

Written by

CEO @ Covalent — https://covalentx.com

Covalent

Covalent

A unified development platform to create and deploy enterprise smart contract systems.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade