From 973d91ec894a5438597855ffb9e53f0a20c18696 Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Wed, 12 Sep 2018 14:49:48 +0200 Subject: Update docs on event data and logs Updates from comments Clarify code comments and add an event output example Clarification from review Updated with information from @gumb0 Add clarifier Updates from review Remove link Update example code --- docs/abi-spec.rst | 2 ++ docs/contracts.rst | 103 ++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 72 insertions(+), 33 deletions(-) diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index f31d9d45..2c206dad 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -405,6 +405,8 @@ Offset ``f`` points to the start of the content of the array ``[[1, 2], [3]]`` w Offset ``g`` points to the start of the content of the array ``["one", "two", "three"]`` which is line 10 (320 bytes); thus ``g = 0x0000000000000000000000000000000000000000000000000000000000000140``. +.. _abi_events: + Events ====== diff --git a/docs/contracts.rst b/docs/contracts.rst index be89727d..95967975 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -756,39 +756,60 @@ converted to ``uint8``. Events ****** -Events allow the convenient usage of the EVM logging facilities, -which in turn can be used to "call" JavaScript callbacks in the user interface -of a dapp, which listen for these events. +Solidity events give an abstraction on top of the EVM's logging functionality. +Applications can subscribe and listen to these events through the RPC interface of an Ethereum client. -Events are -inheritable members of contracts. When they are called, they cause the +Events are inheritable members of contracts. When you call them, they cause the arguments to be stored in the transaction's log - a special data structure -in the blockchain. These logs are associated with the address of -the contract and will be incorporated into the blockchain -and stay there as long as a block is accessible (forever as of -Frontier and Homestead, but this might change with Serenity). Log and -event data is not accessible from within contracts (not even from -the contract that created them). - -"Simple payment verification" (SPV) proofs for logs are possible, so if an external entity supplies -a contract with such a proof, it can check that the log actually -exists inside the blockchain. Be aware that block headers have to be supplied because -the contract can only see the last 256 block hashes. - -Up to three parameters can -receive the attribute ``indexed`` which will cause the respective arguments -to be stored in a special data structure as so-called "topics", which allows them to be searched for, -for example when filtering a sequence of blocks for certain events. Events can always -be filtered by the address of the contract that emitted the event. Also, -the hash of the signature of the event is one of the topics except if you -declared the event with ``anonymous`` specifier. This means that it is -not possible to filter for specific anonymous events by name. +in the blockchain. These logs are associated with the address of the contract, +are incorporated into the blockchain, and stay there as long as a block is +accessible (forever as of the Frontier and Homestead releases, but this might +change with Serenity). The Log and its event data is not accessible from within +contracts (not even from the contract that created them). + +It is possible to request a simple payment verification (SPV) for logs, so if +an external entity supplies a contract with such a verification, it can check +that the log actually exists inside the blockchain. You have to supply block headers +because the contract can only see the last 256 block hashes. + +You can add the attribute ``indexed`` to up to three parameters which adds them +to a special data structure known as :ref:`"topics" ` instead of +the data part of the log. If you use arrays (including ``string`` and ``bytes``) +as indexed arguments, its Keccak-256 hash is stored as a topic instead, this is +because a topic can only hold a single word (32 bytes). + +All parameters without the ``indexed`` attribute are :ref:`ABI-encoded ` +into the data part of the log. + +Topics allow you to search for events, for example when filtering a sequence of +blocks for certain events. You can also filter events by the address of the +contract that emitted the event. + +For example, the code below uses the web3.js ``subscribe(“logs”)`` +`method `_ to filter +logs that match a topic with a certain address value: + +.. code-block:: javascript + + var options = { + fromBlock: 0, + address: web3.eth.defaultAccount, + topics: ["0x0000000000000000000000000000000000000000000000000000000000000000", null, null] + }; + web3.eth.subscribe('logs', options, function (error, result) { + if (!error) + console.log(result); + }) + .on("data", function (log) { + console.log(log); + }) + .on("changed", function (log) { + }); -If arrays (including ``string`` and ``bytes``) are used as indexed arguments, the -Keccak-256 hash of it is stored as topic instead. This is because a topic -can only hold a single word (32 bytes). -All non-indexed arguments will be :ref:`ABI-encoded ` into the data part of the log. +The hash of the signature of the event is one of the topics, except if you +declared the event with the ``anonymous`` specifier. This means that it is +not possible to filter for specific anonymous events by name. :: @@ -811,7 +832,7 @@ All non-indexed arguments will be :ref:`ABI-encoded ` into the data part of } } -The use in the JavaScript API would be as follows: +The use in the JavaScript API is as follows: :: @@ -823,19 +844,35 @@ The use in the JavaScript API would be as follows: // watch for changes event.watch(function(error, result){ - // result will contain various information - // including the arguments given to the `Deposit` - // call. + // result contains non-indexed arguments and topics + // given to the `Deposit` call. if (!error) console.log(result); }); + // Or pass a callback to start watching immediately var event = clientReceipt.Deposit(function(error, result) { if (!error) console.log(result); }); +The output of the above looks like the following (trimmed): + +.. code-block:: json + + { + "returnValues": { + "_from": "0x1111…FFFFCCCC", + "_id": "0x50…sd5adb20", + "_value": "0x420042" + }, + "raw": { + "data": "0x7f…91385", + "topics": ["0xfd4…b4ead7", "0x7f…1a91385"] + } + } + .. index:: ! log Low-Level Interface to Logs -- cgit