Blockchain Development (15) Events and Logs Analysis and Use in Ethereum

Events and Logs in Ethereum are a particularly confusing concept, and this article will help you sort them out.
Because in the last article, we discussed some ways for the Ethereum go-ethereum client to query the transaction list. In this article, we specifically implement a filter discussion. Let's understand how this method is used. The focus is on the last part. Hope it will be helpful to the development. Let's start with the basic concepts to understand the process as a whole.
First of all, Events and Logs in Ethereum are basically the same concept. It is called Events in Solidity and web3.js, and Logs in the Ethereum Yellow Paper. You can understand it as: Ethereum implements the Events function through Logs. The smart contract code writes logs to the blockchain through LOG.
(The same is true if you develop with the Truffle framework, because the Truffle framework itself wraps Web3.js) Where is the
log content located in the blockchain?
The log content is part of the transaction receipt (Transaction Receipts). The entire log content, including other content of Receipts, will generate a ReceiptsRoot and store it in the header of the block. The complete data is stored off-chain.
There are four main purposes of events and logs:
1. Help the user client (web3.js) to read the return value of the smart contract;
2. The smart contract asynchronously informs the user client (web3.js);
3. Used for smart contracts 4.
I think there is a fourth type, which can help us filter out historical transaction data through filter. For the specific implementation, see the analysis in the following article.

Below we explain one by one
1. Help the user client (web3.js) to read the return value
of the smart contract: Suppose the following smart contract:

contract ExampleContract {
  // some state variables ...
  function foo(int256 _value) returns (int256) {
    // manipulate state ...
    return _value;
  }
}

We can simulate calling smart contracts through the message call function of web3.js:

var returnValue = exampleContract.foo.call(2);
console.log(returnValue) // 2

But in a real environment we need to send a transaction (Transaction) to call a smart contract. At this time we will not be able to get the return value of the smart contract. Because the transaction is currently only sent, packaged, and executed for a while (requires the miner's proof of work to achieve). The return value of the call at this time is just the txid or tx hash value of the transaction.

var returnValue = exampleContract.foo.sendTransaction(2, {from: web3.eth.coinbase});
console.log(returnValue) // transaction hash

This is where Events come into play: we often write on-chain methods, or methods that let on-chain data change. We do this by adding Event in front of the method.

//以下是solidity智能合约代码
contract ExampleContract {
  event ReturnValue(address indexed _from, int256 _value);
  unction foo(int256 _value) returns (int256) {
    ReturnValue(msg.sender, _value);
    return _value;
  }
}

//The following is the web3.js user client code

var exampleEvent = exampleContract.ReturnValue({_from: web3.eth.coinbase});
exampleEvent.watch(function(err, result) {
  if (err) {
    console.log(err)
    return;
  }
  console.log(result.args._value)
  // check that result.args._from is web3.eth.coinbase then
  // display result.args._value in the UI and call    
  // exampleEvent.stopWatching()
})
exampleContract.foo.sendTransaction(2, {from: web3.eth.coinbase})

When the transaction is packaged, the callback in web3.js will be called, and then web3.js can get the return value of the smart contract call in the transaction.
As for why the transaction is packaged, the callback in web3.js is called, that is another question, and the simple explanation is as follows. web3.js will be connected to a node in Ethereum. When the node learns that a transaction is written into the block, it will notify the connected node of relevant information.
2. The smart contract notifies the user client asynchronously (web3.js): The
above example is a typical example of the smart contract notifying the user client, but there are more asynchronous calls that can be implemented in a similar way, thus realizing the smart contract asynchronously calling the user capabilities of the client.
Note: Smart contracts are usually written in solidity and run on Ethereum nodes (EVM).
Note: The user client is usually written in web3.js, running on the web server, and web3.js is connected to an Ethereum node.
3. Storage for smart contracts (much cheaper than Storage):
Compared with the storage of smart contract accounts, it is much cheaper to store some information in the form of logs. The approximate price in Storage is: 20,000 gas (Gas) per 32 bytes (256 bits) of storage. The log is roughly 8 gas per byte (Gas).
Let's see an example:

//solidity智能合约代码,模拟用户存款功能
contract CryptoExchange {
  event Deposit(uint256 indexed _market, address indexed _sender, uint256 _amount, uint256 _time);
  function deposit(uint256 _amount, uint256 _market) returns (int256) {
    // perform deposit, update user’s balance, etc
    Deposit(_market, msg.sender, _amount, now);
}

//When a user calls the smart contract to deposit a certain amount, the smart contract needs to actively notify the user client to update the corresponding information.
4. Help us filter out historical transaction data through filter.
The following method specifically implements the method we started to talk about by filtering out historical transaction data from the chain.
//The following is the web3.js code:

var depositEvent = cryptoExContract.Deposit({_sender: userAddress});
depositEvent.watch(function(err, result) {
  if (err) {
    console.log(err)
    return;
  }
  else{
      // append details of result.args to UI
      //将这笔交易写入客户端资料库中,方便以后查询历史交易数据。
  }  
})
//通过增加fromBlock参数指定关注的区块范围,来查询所有的交易数据。(获取链上存储的历史交易数据,我们用扒链的办法来获取,因为eth目前没有提供获取历史数据的API。)
var depositEventAll = cryptoExContract.Deposit({_sender: userAddress}, {fromBlock: 0, toBlock: 'latest'});
depositEventAll.watch(function(err, result) {
  if (err) {
    console.log(err)
    return;
  }
  else{
  // append details of result.args to UI
  //如果不想再被通知可以调用:
  //depositEventAll.stopWatching();
  }
})

//Note: The indexed keyword indicates that the log is indexed by this field to improve query efficiency.
Organized in Shenzhen on December 24, 2017

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325386899&siteId=291194637