Ethereum contracts run on a blockchain and therefore have the characteristics of blockchains: all transactions (state transitions) are traceable and can be replayed by any node in the system. In fact they
are replayed by any node downloading the blockchain from scratch. When the node is up to date, all current storage of the contracts can be queried from a DApp, JSON RPC etc.
How can the
history of the storage be queried?
To give an example, if one were to build a subcurrency using the
Subcurrency example, we would effectively have an altcoin running on Ethereum. Securely transacting with these "coins" is a matter of sending Ethereum transactions to the contract calling its
send
function.
But how would we do things such as:
- Show the transaction history of an address in terms of the subcurrency
- Show transaction details in terms of the subcurrency, i.e. "On 2015-01-05 11:28 an amount of 33 subcoins were transferred from address X to address Y, executed in Ethereum transaction 0x12345 in block 82324"
- Search for addresses that have transacted in the subcoin, even if they don't currently possess coins anymore
Comments
It's applied to for example
web3.eth.getStorageAt()
andweb3.eth.call()
. Without having tested the latest release I would assume the following is possible:- web3.eth.getStorageAt() allows the parameter
- As
- Furthermore, web3.eth.getBlock() allows fetching data about the eth blocks/transactions. The raw input data passed with the transaction is returned, so working with this data requires parsing (i.e. is not as developer friendly as sending the transaction in the first place).
Based on the above I would assume the following is possible in terms of the subcurrency example: This seems to offer quite a range of options to navigate history. I'll report further on my experiences, also about the performance characteristics of these functions.defaultBlock
to be passed. This should allow for getting a storage value at some earlier block. In the case of the Subcurrency example this would allow for checking someone's balance in a past block.web3.eth.getStorageAt()
andweb3.eth.call()
respectweb3.eth.defaultBlock
, I would asssume that calls to Contract objects (e.g. from Solidity) are executed as if they were in the state of a certiain past block.Please correct me if I'm wrong, and supplement with your experiences or tips. Perhaps @chriseth or @KenK can have a look to see if my line of thinking makes sense?
You need your alt coin to generate logs by specifying events in solidity when money is send.
event Send(address from, address to, uint value);
Then you're able to trace all the send from and to and even filter the logs by specifying and address it was send from or to.
This allows you to get all the past transactions of that currency as well.
Example: P.s. i updated the Subcurrency example
Also, with the fromBlock/toBlock it allows for consistent DApp behaviour when the DApp is not continuously running (as with almost all DApps). The DApp can track of the latest block it saw and processed in the UX (for example, notifying the user of transactions in the subcurrency), and store this in e.g.
localStorage
. When opening the DApp again after say a week, it asks for logged events since the last block it processed and will get all relevant transactions in that week.Actually you have to be even more careful, as small chain reorganisations happen all the time.
I check the last block.parentHash i get compare it with the previous ones hash. If there is a mismatch i have a small fork and remove all logs - 100(0) and re-fetch if via filters, to make sure i show the latest correct version of the chain.
If you save a local log to a computer somewhere, you no longer have a decentralized solution, with the usual trust issues.
Sure they should validate with the current blockchain and update data accordingly, but if every dapp would always get all past data of millions of blocks from the node, the node would be under heavy stress, thats for sure
Many Thanks!