Actions

Offchain reporting: Difference between revisions

From Chainlink Community Wiki

No edit summary
No edit summary
Line 5: Line 5:
<p>The migration resulted in an exponential increase in efficiency and an overall easier experience as a Chainlink Node Operator.</p>
<p>The migration resulted in an exponential increase in efficiency and an overall easier experience as a Chainlink Node Operator.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Migration to Offchain Reporting: ETH / USD</h2>
<h2> <span style="color:#36c"> Migration to Offchain Reporting: ETH / USD </span> </h2>


<p>'''Oct 21:''' The Proxy is updated to point to the OCR Contract, with the FluxMonitor contract as a failover.</p>
<p>'''Oct 21:''' The Proxy is updated to point to the OCR Contract, with the FluxMonitor contract as a failover.</p>
Line 20: Line 20:
== <span style="color:#36c"> OffchainReporting (OCR) Operational Overview: </span> ==
== <span style="color:#36c"> OffchainReporting (OCR) Operational Overview: </span> ==


==== The OCR feeds are designed with access control and high availability in mind. ====
==== <span style="color:#36c"> The OCR feeds are designed with access control and high availability in mind. </span> ====
In case of a contract or network failure, there are failover points designed into the system.
In case of a contract or network failure, there are failover points designed into the system.


=== In the details below, we will be looking at the ETH / USD price feed. ===
=== <span style="color:#36c"> In the details below, we will be looking at the ETH / USD price feed. </span> ===
The following example is specific to a standard price feed.  It’s important to note that there are numerous specific use-case contracts in production that may have different designs, but the general contract design will remain applicable.
The following example is specific to a standard price feed.  It’s important to note that there are numerous specific use-case contracts in production that may have different designs, but the general contract design will remain applicable.
[[File:OcrOverview.png|center|frameless|1100x1100px]]
[[File:OcrOverview.png|center|frameless|1100x1100px]]
<p>
<p>


=== Important Definitions: ===
=== <span style="color:#36c"> Important Definitions: </span> ===


==== Deviation Threshold: ====
==== <span style="color:#36c"> Deviation Threshold: </span> ====
The value that an asset needs to deviate from the previously reported value.
The value that an asset needs to deviate from the previously reported value.


Maintaining the example of the ETH / USD price feed, if the <span style="font-family:Courier;">AccessControlledOffchainAggregators</span> most recently reported value of Ethereum is <span style="font-family:Courier;">451804000000</span> or <span style="font-family:Courier;">$4,518.04</span>, and a single Chainlink node operator’s calculated value deviates from that value greater than <span style="font-family:Courier;">0.5%</span> (<span style="font-family:Courier;">± 2259020000</span> or <span style="font-family:Courier;">± $22.59</span>), a new round will be fired and the new aggregate value will be written to chain.
Maintaining the example of the ETH / USD price feed, if the <span style="font-family:Courier;">AccessControlledOffchainAggregators</span> most recently reported value of Ethereum is <span style="font-family:Courier;">451804000000</span> or <span style="font-family:Courier;">$4,518.04</span>, and a single Chainlink node operator’s calculated value deviates from that value greater than <span style="font-family:Courier;">0.5%</span> (<span style="font-family:Courier;">± 2259020000</span> or <span style="font-family:Courier;">± $22.59</span>), a new round will be fired and the new aggregate value will be written to chain.


==== Heartbeat: ====
==== <span style="color:#36c"> Heartbeat: </span> ====
Maximum age of an on-chain asset value.
Maximum age of an on-chain asset value.


If the deviation threshold is not reached within the time of the heartbeat, the feed will be updated.  The heartbeat for the ETH / USD feed is one hour.  For example, if the price of Ethereum is stable enough to node deviate greater than <span style="font-family:Courier;">0.5%</span> for an hour, a new round will be fired off regardless of the deviation threshold.
If the deviation threshold is not reached within the time of the heartbeat, the feed will be updated.  The heartbeat for the ETH / USD feed is one hour.  For example, if the price of Ethereum is stable enough to node deviate greater than <span style="font-family:Courier;">0.5%</span> for an hour, a new round will be fired off regardless of the deviation threshold.


==== Observer: ====
==== <span style="color:#36c"> Observer: </span> ====
For each round of a price feed, each Chainlink node is responsible for submitting observations.  These observations are an aggregate of multiple data sources; typically a median.
For each round of a price feed, each Chainlink node is responsible for submitting observations.  These observations are an aggregate of multiple data sources; typically a median.


For each round a Chainlink node participates in, they’re rewarded an observation payment.
For each round a Chainlink node participates in, they’re rewarded an observation payment.


==== Transmitter: ====
==== <span style="color:#36c"> Transmitter: </span> ====
While every Chainlink node is expected to participate in observations, only one Chainlink node is (initially) pseudo-randomly elected to transmit the agreed upon aggregate value that is calculated from all observations.
While every Chainlink node is expected to participate in observations, only one Chainlink node is (initially) pseudo-randomly elected to transmit the agreed upon aggregate value that is calculated from all observations.


Line 52: Line 52:
If the initial transmitter is unable to transmit the transaction within a reasonable time, two additional transmitters are elected, creating a race condition.
If the initial transmitter is unable to transmit the transaction within a reasonable time, two additional transmitters are elected, creating a race condition.


=== Contract Descriptions: ===
=== <span style="color:#36c"> Contract Descriptions: </span> ===
There are three major contracts to be aware of:
There are three major contracts to be aware of:


Line 59: Line 59:
* <span style="font-family:Courier;">AccessControlledOffchainAggregator</span>
* <span style="font-family:Courier;">AccessControlledOffchainAggregator</span>


==== EACAggregatorProxy: ====
==== <span style="color:#36c"> EACAggregatorProxy: </span> ====
This is the proxy contract that consumer contracts will read data from.  This contract is designed to enable an active passive data source. If we take a look at the aggregator that the ETH / USD proxy points to, we’ll see that it is the address of the ETH / USD <span style="font-family:Courier;">AccessControlledOffchainAggregator<span>.
This is the proxy contract that consumer contracts will read data from.  This contract is designed to enable an active passive data source. If we take a look at the aggregator that the ETH / USD proxy points to, we’ll see that it is the address of the ETH / USD <span style="font-family:Courier;">AccessControlledOffchainAggregator<span>.


Line 66: Line 66:
It gets a little obfuscated if we look at the <span style="font-family:Courier;">proposedAggregator</span>, as that shows as <span style="font-family:Courier;">0x0000000000000000000000000000000000000000</span>.  However; this is tied to a flag contract, which the operation of is outside the scope of this documentation.  The important takeaway is that the proxy tentatively points at a backup price feed that is almost identical to the primary, but is highly secure.
It gets a little obfuscated if we look at the <span style="font-family:Courier;">proposedAggregator</span>, as that shows as <span style="font-family:Courier;">0x0000000000000000000000000000000000000000</span>.  However; this is tied to a flag contract, which the operation of is outside the scope of this documentation.  The important takeaway is that the proxy tentatively points at a backup price feed that is almost identical to the primary, but is highly secure.


==== AccessControlledOffchainAggregator: ====
==== <span style="color:#36c"> AccessControlledOffchainAggregator: </span> ====
This is the contract that the node operators provide price updates to.  If we take a look at the ETH / USD example above (<span style="font-family:Courier;">0x37bC7498f4FF12C19678ee8fE19d713b87F6a9e6</span>), we can see quite a few getters for this contract.
This is the contract that the node operators provide price updates to.  If we take a look at the ETH / USD example above (<span style="font-family:Courier;">0x37bC7498f4FF12C19678ee8fE19d713b87F6a9e6</span>), we can see quite a few getters for this contract.


Line 85: Line 85:
We can see that the contract is referencing another contract, the <span style="font-family:Courier;">requesterAccessController</span> at address <span style="font-family:Courier;">0x641b698ad1c6e503470520b0eecb472c0589dfe6</span>.
We can see that the contract is referencing another contract, the <span style="font-family:Courier;">requesterAccessController</span> at address <span style="font-family:Courier;">0x641b698ad1c6e503470520b0eecb472c0589dfe6</span>.


==== SimpleWriteAccessController: ====
==== <span style="color:#36c"> SimpleWriteAccessController: </span> ====
The <span style="font-family:Courier;">SimpleWriteAccessController</span>’s purposes is to control which contracts can read and/or write to a contract.  Read and write access for both the <span style="font-family:Courier;">EACAggregatorProxy</span> and the <span style="font-family:Courier;">AccessControlledOffchainAggregator</span> can be managed by the <span style="font-family:Courier;">SimpleWriteAccessController</span>.
The <span style="font-family:Courier;">SimpleWriteAccessController</span>’s purposes is to control which contracts can read and/or write to a contract.  Read and write access for both the <span style="font-family:Courier;">EACAggregatorProxy</span> and the <span style="font-family:Courier;">AccessControlledOffchainAggregator</span> can be managed by the <span style="font-family:Courier;">SimpleWriteAccessController</span>.


Line 92: Line 92:
In short, this enables the contract owner to have data on-chain which is only accessible to the desired contracts.
In short, this enables the contract owner to have data on-chain which is only accessible to the desired contracts.


=== Diagrams: ===
=== <span style="color:#36c"> Diagrams: </span> ===
In this section, you will find diagrams representing the relationships between each of the above contracts.
In this section, you will find diagrams representing the relationships between each of the above contracts.


==== SimpleWriteAccessController: ====
==== <span style="color:#36c"> SimpleWriteAccessController: </span> ====
Here we can see the ConsumerContract requesting the latest round data from the <span style="font-family:Courier;">EACAggregatorProxy</span> contract.  Before the <span style="font-family:Courier;">EACAggregatorProxy</span> provides the response to the <span style="font-family:Courier;">ConsumerContract</span>, it will check the <span style="font-family:Courier;">SimpleReadAccessControl</span> function in the <span style="font-family:Courier;">SimpleWriteAccessControl</span> contract.  It will compare the requesting <span style="font-family:Courier;">ConsumerContract</span>’s address against the <span style="font-family:Courier;">AccessList</span>.  If the requesting <span style="font-family:Courier;">ConsumerContract</span> address is found in the <span style="font-family:Courier;">AccessList</span>, it will be able to read the lastestRound response from the <span style="font-family:Courier;">EACAggregatorProxy</span>.
Here we can see the ConsumerContract requesting the latest round data from the <span style="font-family:Courier;">EACAggregatorProxy</span> contract.  Before the <span style="font-family:Courier;">EACAggregatorProxy</span> provides the response to the <span style="font-family:Courier;">ConsumerContract</span>, it will check the <span style="font-family:Courier;">SimpleReadAccessControl</span> function in the <span style="font-family:Courier;">SimpleWriteAccessControl</span> contract.  It will compare the requesting <span style="font-family:Courier;">ConsumerContract</span>’s address against the <span style="font-family:Courier;">AccessList</span>.  If the requesting <span style="font-family:Courier;">ConsumerContract</span> address is found in the <span style="font-family:Courier;">AccessList</span>, it will be able to read the lastestRound response from the <span style="font-family:Courier;">EACAggregatorProxy</span>.


[[File:SimpleWriteAccessControllerDiagram.png]]
[[File:SimpleWriteAccessControllerDiagram.png]]


==== EACAggregatorProxy Failover Design: ====
==== <span style="color:#36c"> EACAggregatorProxy Failover Design: </span> ====
Here we can see the proxy contract pointing at the primary aggregator.  In case of a failure event, the proxy contract can be pointed to another aggregator contract, without the consumer having to make any adjustments on their end.
Here we can see the proxy contract pointing at the primary aggregator.  In case of a failure event, the proxy contract can be pointed to another aggregator contract, without the consumer having to make any adjustments on their end.


[[File:ProxyFailoverdiagram.png]]
[[File:ProxyFailoverdiagram.png]]


==== AccessControlledOffchainAggregator ====
==== <span style="color:#36c"> AccessControlledOffchainAggregator </span> ====
The <span style="font-family:Courier;">AccessControlledOffchainAggregator</span> is the contract that each Chainlink node interacts with.
The <span style="font-family:Courier;">AccessControlledOffchainAggregator</span> is the contract that each Chainlink node interacts with.


Line 112: Line 112:
For the purpose of this document, we will highlight a couple of them:
For the purpose of this document, we will highlight a couple of them:


===== Calculating the Aggregate Value for Each Round =====
===== <span style="color:#36c"> Calculating the Aggregate Value for Each Round </span> =====
In the following diagram, we can see each of the Chainlink nodes querying three different data sources.
In the following diagram, we can see each of the Chainlink nodes querying three different data sources.



Revision as of 19:26, 20 April 2022

Price Feeds Offchain Reporting (OCR)

Migrating from FluxMonitor to Offchain Reporting was by far the most impressive upgrade, and the increase in efficiency was, and is, simply amazing.

The migration resulted in an exponential increase in efficiency and an overall easier experience as a Chainlink Node Operator.

 

Migration to Offchain Reporting: ETH / USD

Oct 21: The Proxy is updated to point to the OCR Contract, with the FluxMonitor contract as a failover.

11 May 21: The first transmissions for the ETH / USD Price Feed were broadcast on-chain.

06 May 21: The ETH / USD AccessControlledOffchainAggregator contract was deployed

at address 0x37bC7498f4FF12C19678ee8fE19d713b87F6a9e6
at transaction hash 0x3442b045dde57720c72992dbc2dfd4ea0c608bdbe1d561cb584c1e2681e9edc7

OffchainReporting (OCR) Operational Overview:

The OCR feeds are designed with access control and high availability in mind.

In case of a contract or network failure, there are failover points designed into the system.

In the details below, we will be looking at the ETH / USD price feed.

The following example is specific to a standard price feed.  It’s important to note that there are numerous specific use-case contracts in production that may have different designs, but the general contract design will remain applicable.

OcrOverview.png

Important Definitions:

Deviation Threshold:

The value that an asset needs to deviate from the previously reported value.

Maintaining the example of the ETH / USD price feed, if the AccessControlledOffchainAggregators most recently reported value of Ethereum is 451804000000 or $4,518.04, and a single Chainlink node operator’s calculated value deviates from that value greater than 0.5% (± 2259020000 or ± $22.59), a new round will be fired and the new aggregate value will be written to chain.

Heartbeat:

Maximum age of an on-chain asset value.

If the deviation threshold is not reached within the time of the heartbeat, the feed will be updated.  The heartbeat for the ETH / USD feed is one hour.  For example, if the price of Ethereum is stable enough to node deviate greater than 0.5% for an hour, a new round will be fired off regardless of the deviation threshold.

Observer:

For each round of a price feed, each Chainlink node is responsible for submitting observations.  These observations are an aggregate of multiple data sources; typically a median.

For each round a Chainlink node participates in, they’re rewarded an observation payment.

Transmitter:

While every Chainlink node is expected to participate in observations, only one Chainlink node is (initially) pseudo-randomly elected to transmit the agreed upon aggregate value that is calculated from all observations.

The transmitter is compensated for their observation, reimbursed for the gas fees spent on broadcasting the transaction, and is rewarded a transmitter bonus.

If the initial transmitter is unable to transmit the transaction within a reasonable time, two additional transmitters are elected, creating a race condition.

Contract Descriptions:

There are three major contracts to be aware of:

  • EACAggregatorProxy
  • SimpleWriteAccessController
  • AccessControlledOffchainAggregator

EACAggregatorProxy:

This is the proxy contract that consumer contracts will read data from.  This contract is designed to enable an active passive data source. If we take a look at the aggregator that the ETH / USD proxy points to, we’ll see that it is the address of the ETH / USD AccessControlledOffchainAggregator.

EACAggregatorProxy.png

It gets a little obfuscated if we look at the proposedAggregator, as that shows as 0x0000000000000000000000000000000000000000.  However; this is tied to a flag contract, which the operation of is outside the scope of this documentation.  The important takeaway is that the proxy tentatively points at a backup price feed that is almost identical to the primary, but is highly secure.

AccessControlledOffchainAggregator:

This is the contract that the node operators provide price updates to.  If we take a look at the ETH / USD example above (0x37bC7498f4FF12C19678ee8fE19d713b87F6a9e6), we can see quite a few getters for this contract.

We’ll focus on three of these in this documentation.

  • description
  • latestAnswer
  • requesterAccessController

AccessControlledOffchainAggregatorExample.png

We can see that the description is ETH / USD.

We can see that the latestAnswer is 451804000000.

  • If we adjust for decimal places, we’ll know that the price of ethereum during this round was $4,518.04.

We can see that the contract is referencing another contract, the requesterAccessController at address 0x641b698ad1c6e503470520b0eecb472c0589dfe6.

SimpleWriteAccessController:

The SimpleWriteAccessController’s purposes is to control which contracts can read and/or write to a contract.  Read and write access for both the EACAggregatorProxy and the AccessControlledOffchainAggregator can be managed by the SimpleWriteAccessController.

To manage access, there is an AccessList in the SimpleWriteAccessController that will track which contracts are able to read and/or write to/from the EACAggregatorProxy and AccessControlledOffchainAggregator.

In short, this enables the contract owner to have data on-chain which is only accessible to the desired contracts.

Diagrams:

In this section, you will find diagrams representing the relationships between each of the above contracts.

SimpleWriteAccessController:

Here we can see the ConsumerContract requesting the latest round data from the EACAggregatorProxy contract.  Before the EACAggregatorProxy provides the response to the ConsumerContract, it will check the SimpleReadAccessControl function in the SimpleWriteAccessControl contract.  It will compare the requesting ConsumerContract’s address against the AccessList.  If the requesting ConsumerContract address is found in the AccessList, it will be able to read the lastestRound response from the EACAggregatorProxy.

SimpleWriteAccessControllerDiagram.png

EACAggregatorProxy Failover Design:

Here we can see the proxy contract pointing at the primary aggregator.  In case of a failure event, the proxy contract can be pointed to another aggregator contract, without the consumer having to make any adjustments on their end.

ProxyFailoverdiagram.png

AccessControlledOffchainAggregator

The AccessControlledOffchainAggregator is the contract that each Chainlink node interacts with.

At the contract level, the AccessControlledOffchainAggregator tracks quite a bit of information.

For the purpose of this document, we will highlight a couple of them:

Calculating the Aggregate Value for Each Round

In the following diagram, we can see each of the Chainlink nodes querying three different data sources.

Of these three data sources, each Chainlink node will calculate the median value and report it to the other nodes.

Once a minimum threshold of nodes have reported their values, a median of medians is then calculated.

Each Chainlink node signs the calculated aggregate value.

This aggregated, median of medians, value is what the contract will receive as the latestAnswer

PriceFeedFullView.png


https://www.youtube.com/watch?v=hN91vq6yHRM

Off-chain Reporting resources

XXTEXTXX

Timeline

Date Media Author Title
24 Feb 21 Article Chainlink Chainlink Achieves Major Scalability Upgrade With Mainnet Launch of Off-Chain Reporting (OCR)

Educational

Date Media Author Title
N/A Official Docs Chainlink Off-Chain Reporting- Official Chainlink Documentation
08 Oct 22 Video Chainlink Looking Under the Hood of OCR 2.0: Product Deep Dive | Lorenz Breidenbach at SmartCon 2022
24 Feb 21 Research Chainlink Chainlink Off-chain Reporting Protocol
Feb 21 Research Smart Contract Research Forum Research Summary - Chainlink Off-Chain Reporting Protocol
27 Jan 21 Article Reputation Link Off-Chain Reporting - Technical Overview