Basic principle of chainlink Oracle

Time:2020-7-23

Basic principles of chainlink
In this paper, we will briefly describe the basic principle of chainlink from the technical point of view. If we use the shortest sentence to explain what chainlink is, we can say that chainlink is a decentralized Oracle project. Therefore, in order to understand the working principle of chainlink, we must first understand what is the oracle.

Prophecy machine

Oracle’s English is Oracle, which has the same name as Oracle, a famous database service provider. However, they have no relationship except the same name. What does the word Oracle mean? Here’s what I’m doing here vocabulary.com The meaning of Oracle found on:

Back in ancient times, an Oracle was someone who offered advice or a prophecy thought to have come directly from a divine source. In modern usage, any good source of information can be called an oracle.

In ancient times, oracle was a person who made suggestions or prophecies. His suggestions or prophecies were believed to come directly from God. In modern usage, any good source of information can be called oracle.

In this way, it is not difficult to understand that Oracle conveys the will of omnipotent omniscient God. Oracle bone inscriptions were originally used to record auspicious and ominous omens. At that time, they were also regarded as Oracle, conveying the meaning of God. Both Oracle and Oracle express the meaning of “information source”.

The word Oracle in the field of computer was first put forward by Turing. Based on Turing machine, Turing added a black box called Oracle to form Oracle machine. The so-called prophet is an entity that can answer a specific set of questions. In other words, it can input information into the Turing machine system to help Turing machine complete the calculation. The “Turing machine” can be referred to as “Turing machine” in the sense of “Turing machine” in the sense of “complete contract“. Therefore, the name “oracle” is not an original concept in the field of blockchain technology. It comes from the very early computer abstract design, and there are similar concepts in cryptography and other fields.

In the field of blockchain, Oracle is considered to be a system that can provide external data sources for smart contracts. From the perspective of traditional technology architecture, Oracle is a middleware connecting smart contract with the outside world of blockchain, and is an important infrastructure of blockchain. Its function is to provide data information for smart contract on blockchain.

As defined by Ethereum, blockchain is a transaction based state machine. What it can do is very simple, that is, it can change the blockchain from one state to another by submitting transactions / transactions to the blockchain. In order to maintain consensus, the execution of EVM must be fully deterministic and based only on the shared context of Ethereum state and signed transactions. This leads to two particularly important consequences: one is that EVM and smart contracts have no inherent random sources; the other is that external data can only be introduced as data payload of transactions. In popular words, blockchain does not have the ability to obtain data actively. It can only use the data of the blockchain itself. Due to the lack of data, the application scope of smart contract is very small. At present, most of the applications are based on token.

The certainty of blockchain means that on any node, as long as it is connected to the blockchain’s distributed network, it can synchronize all the historical blocks and play back a set of identical account books. In other words: without an Internet connection, given a complete block, the node must be able to recreate the final state of the blockchain from scratch. If the ledger depends on the result of an external API call during the formation process, the playback result will be different at different times and in different environments. This situation is not allowed by the blockchain, so the blockchain has no network calls at the beginning of its design.

So what should be done to provide data to the blockchain? The blockchain can only leave the account book, while the blockchain can input only transactions. We will start from these two aspects.

Basic principle of chainlink Oracle

Almost every contract system has the function of event recording, such as the eventlog function in Ethereum.

Let’s introduce the basic principle of Oracle through an example. We set up a user contract on the Ethereum chain, which needs to obtain the temperature data of a city. Of course, the smart contract itself is unable to obtain the data information that occurs in the real world under the chain, and it needs to be realized with the help of Oracle. The smart contract writes the city that needs to obtain the weather temperature to the eventlog. Under the chain, we will start a process, listen to and subscribe to the event log. After obtaining the request of the smart contract, we will call the backfill method in the contract to submit the temperature of the specified city to the smart contract by submitting the transaction.

Statement: the following code only demonstrates the Oracle principle, without parameter detection and error handling, please do not use in the production environment.

Consumer contract:

contract WeatherOracle {
  //User stores weather value submitted by Oracle
  uint256 public temperature;

  //Defining events
  event RequestTemperature (bytes city);

  //A get request is issued, that is, an event log is issued
  function requestTemperature (string memory _city) public {
    emit RequestTemperature(bytes(_city));
  }

  //Oracle callback method. After the Oracle gets the data, it submits the data to the chain through this method
  function updateWeather (uint256 _temperature) public {
    temperature = _temperature;
  }
}

The above code is very simple. It defines a variable to store the result, a method to make a request, and a method to receive the result.

Under the chain, we start a process to obtain the log information by subscribing to the topic, and then submit a result to the contract by building a transaction.

func SubscribeEventLog() {
  topic := crypto.Keccak256([]byte("RequestTemperature(bytes)"))
  query := ethereum.FilterQuery{
    Topics: [][]common.Hash{
      {
        common.BytesToHash(topic),
      },
    },
  }

  //Subscribe to log events for related topics
  events := make(chan types.Log)
  sub, err := EthClient.SubscribeFilterLogs(ctx, query, events)

  //Load ABI file of contract
  ta, err := abi.JSON(strings.NewReader(AbiJsonStr))

  //Listening event subscription
  for {
    select {
    case err := <-sub.Err():
      log.Error(err)
      break
    case ev := <-events:
      //Get the message of subscription
      ej, _ := ev.MarshalJSON()
      log.Info(string(ej))

      //Parsing data
      var sampleEvent struct {
        City []byte
      }
      err = ta.Unpack(&sampleEvent, "RequestTemperature", ev.Data)
      log.Info(string(sampleEvent.City))

      //To build the transaction submission result, you need to provide a private key for signing the transaction
      CallContract("b7b502b...164b42c")
    }
  }
}
func CallContract(keyStr string) {
  addr := PrivateKeyToAddress(keyStr)
  nonce, err := EthClient.PendingNonceAt(ctx, addr)

  gasPrice, err := EthClient.SuggestGasPrice(ctx)

  privateKey, err := crypto.HexToECDSA(keyStr)

  auth := bind.NewKeyedTransactor(privateKey)
  auth.Nonce = big.NewInt(int64(nonce))
  auth.Value = big.NewInt(0)
  auth.GasLimit = uint64(300000)
  auth.GasPrice = gasPrice

  instance, err := event.NewEvent(common.HexToAddress("0x8A421906e9562AA1c71e5a32De1cf75161C5A463"), EthClient)

  //Call the updateweather method in the contract to backfill the data "29"
  tx, err := instance.UpdateWeather(auth, big.NewInt(29))

  log.Info(tx.Hash().Hex())
}

Use a diagram to show the process:

Basic principle of chainlink Oracle

Chainlink

Chainlink is a decentralized Oracle project. Its role is to provide the blockchain with real-world data in the most secure way. Based on the realization of the basic Oracle principle, chainlink establishes a virtuous cycle ecosystem around link token through economic incentives. Chainlink Oracle needs to be triggered through the transfer of link token.

Link is the erc677 contract on the Ethereum network. Please refer to this article for the differences of various ERC tokens.

In the book “Mastering Ethereum”, three design patterns of Oracle are proposed

  • Immediate read
  • Publish – subscribe
  • Request – response

The Oracle function based on link erc677 token belongs to the request / response mode. This is a more complex pattern. The figure above shows a simple request / corresponding process without aggregation process.

Basic principle of chainlink Oracle

We offer it in chainlinkTestnetConsumerOne of the contractsrequestEthereumPriceMethod as an example to briefly talk about the process of request response. This function is defined as follows:

function requestEthereumPrice(address _oracle, string _jobId)
  public
  onlyOwner
{
  Chainlink.Request memory req = buildChainlinkRequest(stringToBytes32(_jobId), this, this.fulfillEthereumPrice.selector);
  req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD");
  req.add("path", "USD");
  req.addInt("times", 100);
  sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT);
}

Its function is to obtain the transaction price of eth / USD from the specified API (cryptocompare). The parameters passed in by the function are the specified Oracle address and jobid. After setting the request parameters of some columns, callsendChainlinkRequestToMethod to issue the request.sendChainlinkRequestToIt is an interface method defined in the library provided by chainlink. It is defined as follows:

/**
  *@ notice creates a request to the specified Oracle address
  *@ dev creates and stores a request ID, increases the local nonce value, and sends the link using the 'transferandcall' method,
  *Create a request to the target Oracle contract address
  *Issue the chainlinkrequested event
  * @param _ Oracle address to which Oracle sends the request
  * @param _ Req completes the initialization of the chainlink request
  * @param _ Number of links sent by payment request
  *@ return request ID
  */
function sendChainlinkRequestTo(address _oracle, Chainlink.Request memory _req, uint256 _payment)
  internal
  returns (bytes32 requestId)
{
  requestId = keccak256(abi.encodePacked(this, requests));
  _req.nonce = requests;
  pendingRequests[requestId] = _oracle;
  emit ChainlinkRequested(requestId);
  require(link.transferAndCall(_oracle, _payment, encodeRequest(_req)), "unable to transferAndCall to oracle");
  requests += 1;

  return requestId;
}

amonglink.transferAndCallThe method is the token transfer method defined by erc677 and erc20transferThere is one more methoddataField, which can carry data at the same time of transfer. Here, the packaged request data is put in the data field and sent to the Oracle contract along with the transfer.transferAndCallMethods are defined as follows:

/**
  *@ dev transfers the token along with the extra data to a contract address
  * @param _ To the destination address of the transfer to
  * @param _ Number of value transfers
  * @param _ Data additional data passed to the receiving contract
  */
  function transferAndCall(address _to, uint _value, bytes _data)
    public
    returns (bool success)
  {
    super.transfer(_to, _value);
    Transfer(msg.sender, _to, _value, _data);
    if (isContract(_to)) {
      contractFallback(_to, _value, _data);
    }
    return true;
  }

Among themTransfer(msg.sender, _to, _value, _data);Is to issue an event log:

event Transfer(address indexed from, address indexed to, uint value, bytes data);

Record the details of the transfer (sender, receiver, amount, data) into the log.

After the transfer is received, the Oracle contract will triggeronTokenTransferMethod, which checks the validity of the transfer and passes theOracleRequestEvent records more detailed data information:

event OracleRequest(
  bytes32 indexed specId,
  address requester,
  bytes32 requestId,
  uint256 payment,
  address callbackAddr,
  bytes4 callbackFunctionId,
  uint256 cancelExpiration,
  uint256 dataVersion,
  bytes data
);

This log will be found in the Oracle contract log, as shown at the bottom of the figure. The nodes under the chain will subscribe to the log of the topic. After obtaining the log information, the node will resolve the specific information of the request and obtain the result of the request through the API call of the network. After that, it calls thefulfillOracleRequestMethod to submit data to the chain.fulfillOracleRequestIt is defined as follows:

/**
  *@ notice is called by the chainlink node to complete the request
  *The parameter submitted by @ dev must be the hash parameter recorded by the 'oraclequest' method
  *The callback function of the callback address will be called. No error will be reported during the 'require' check, so that nodes can get paid
  * @param _ Requestid the request ID must match the requester
  * @param _ Payment is the payment amount issued by Oracle (in Wei)
  * @param _ Callback address the callback address of the completion method
  * @param _ Callback function for callbackfunctionid completion method
  * @param _ The expiration requester can cancel the expiration time that the node should respond before
  * @param _ Data the data returned to the consumer contract
  *@ return status value of successful external call
  */
function fulfillOracleRequest(
  bytes32 _requestId,
  uint256 _payment,
  address _callbackAddress,
  bytes4 _callbackFunctionId,
  uint256 _expiration,
  bytes32 _data
)
  external
  onlyAuthorizedNode
  isValidRequest(_requestId)
  returns (bool)
{
  bytes32 paramsHash = keccak256(
    abi.encodePacked(
      _payment,
      _callbackAddress,
      _callbackFunctionId,
      _expiration
    )
  );
  require(commitments[_requestId] == paramsHash, "Params do not match request ID");
  withdrawableTokens = withdrawableTokens.add(_payment);
  delete commitments[_requestId];
  require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas");
  // All updates to the oracle's fulfillment should come before calling the
  // callback(addr+functionId) as it is untrusted.
  // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern
  return _callbackAddress.call(_callbackFunctionId, _requestId, _data); // solhint-disable-line avoid-low-level-calls
}

After a series of tests, this method will return the results to the consumer contract through the previously recorded callback address and callback function:

_callbackAddress.call(_callbackFunctionId, _requestId, _data);

In this way, all requests are completed.

summary

Starting from the concept of Oracle, this paper explains the basic process of chainlink Oracle in request / response mode through a simple example of obtaining eth price, hoping to help you understand the operation principle of Oracle and chainlink.

reference resources:
https://medium.com/@liyunlong…

Welcome to the chainlink developer community

Basic principle of chainlink Oracle