Oracle Decision Model
From the software architecture perspective, a blockchain could be used as a component or connector within a large software system. Blockchain-based solutions typically need to send/receive data to/from off-chain components. However, as the execution environment of blockchain is self-contained, it can only access data included in transactions and the global state. An oracle is used to bridge blockchain with the external world. An oracle can be characterized along three dimensions: the direction of the data flow, the initiator of the data flow, and the decentralization of the deployment. Thus, the patterns in this category cover such dimensions of oracles. The oracle decision model is shown below figure. This decision model could be skipped for use cases that can operate purely on the transaction and global state, e.g., cryptocurrencies.
When it comes to the oracle deployment options, a centralized oracle could be applied to collect the external state. The centralized oracle introduces a trusted third-party into the blockchain system to verify the external state. Such a centralized oracle component becomes a single point of failure, whose unavailability, failure, or compromise may prevent blockchain from completing the transaction validation. To overcome a single point of failure, a decentralized oracle consisting of multiple external servers and independent data sources could be used. In this case, the voting pattern could be used with multiple decentralized oracles to reach consensus on the external state. For example, k-of-m threshold signature could be used by multiple oracles to sign on the same value to be written on to the blockchain.
The direction of the data flow is typically the first factor to consider. If the data flow from the external world to the blockchain, an inbound oracle is used to transfer data from the external world to the blockchain. Depending on the initiator of the data flow, we can choose either a pull-based inbound oracle or a push-based inbound oracle pattern.
When a smart contract requests an off-chain state/data, the pull-based inbound oracle receives the request from the caller smart contract, gathers the state from off-chain components, and sends the state back to the caller using a transaction. This process is transparent as it is implemented using smart contracts that communicate via delegated calls. A pull-based inbound oracle’s performance is constrained by the transaction rate of the blockchain network and the time needed to collect external data once the request is made to the oracle.
A push-based inbound oracle uses off-chain components to monitor external state/data changes and proactively injects any updates into the blockchain. This enhances the performance as the calling smart contract does not need to wait for the oracle to collect data. However, because such a push-based inbound oracle is not deployed on blockchain as a smart contract, the data provision depends on an off-chain component that does not have security guarantees similar to the blockchain. If the use case needs to resolve temporal conflicts, the history oracle pattern could be applied to complement push-based inbound oracle to provide historical values of off-chain data. In these patterns, how the data came into existence is invisible.
If the data flow from blockchain to the external world, an outbound oracle can be used to transfer data from blockchain to the external system. Similar to in-bound oracles, there are push-based outbound oracles and pull-based outbound oracles. The former keeps monitoring the blockchain for relevant updates. For example, watching the events logged in Solidity smart contract, and subsequently triggering relevant off-chain activities. Alternatively, a pull-based outbound oracle query on-chain data on demand.