Ethereum Archive – Viewing an Item
In the post Ethereum as a Decentralized Archive we developed a simple item contract for archiving. The item held the hash of a file along with metadata describing the file.
What we now need is a way to view an item contract on the Ethereum network. The easiest way is to display the item in a web page and the Ethereum project provides a convenient Javascript library for interacting with the blockchain called Web.js. So we’re going to use this for retrieving our archived item and displaying it using HTML.
Before breaking it down, I encourage you to look at the full code for this and other Ethereum-based archive functionality on our KnowledgeArc.Network Github. All user interface code is available under the ui directory.
Currently, this is a proof of concept. Therefore, it is recommended you do NOT deploy the Ethereum contract on the mainnet blockchain.
How it works
When a contract is deployed to the Ethereum network, a contract address is returned:
var web3 = new Web3(new Web3.providers.HttpProvider("https://ropsten.infura.io/"));
var contractAddress = "0xabaf9d2955e0ce3e53d0fd964e761017d0a0a957";
var contract = web3.eth.contract(abi).at(contractAddress);
For now, I have hard coded my the address of a contract I deployed earlier. If you deploy your own using Item.sol you would simply replace contractAddress with the one returned by the Ethereum virtual machine.
The contract used above is deployed to the Ropsten test network but it could just as easily be deployed to any Ethereum blockchain; another testnet or even a local testnet.
Before I explain what the rest of the code is doing I will explain the abi variable and its purpose. The abi variable stores the Application Binary Interface (hence ABI), which describes which external programming interfaces are exposed by the Ethereum contract (if you are interested in delving further, ABI is described in more detail in the Ethereum documentation). Our archived item’s abi details are stored in a separate Javascript file called abi.js.
Now that we have a connection to our contract (I.e. through the contract object) we can make calls to the Item contract’s methods. Making calls to contract methods is very straighforward. It is simply:
contact.methodname.call()
where methodname is the name of the method in the contract we want to call. So, for the Item contract we make a call to get a field count as well as retrieve individual metadata fields. Getting a field count simply reqiures a call to the getFieldCount method:
contact.getFieldCount.call()
And we loop across the fields, requesting each field name and value:
for (var i = 0; i < fieldCount; i++) {
data[i] =
{
"name":String(contract.getFieldName.call(i)),
"value":String(contract.getFieldValue.call(i))
};
}
You may be wondering why the returned value is explicitly type cast using the Number() and String() methods. This is because the web.js call() method often returns values as objects (even integers). So, for, say, the field count, by type casting, we get the actual count rather than an object representing the count.
For those interested, the above method calls are view calls. This means there is no gas cost associated in calling these methods.
So in summary, we retrieve the contract by its address, then retrieve values using the various view methods, getFieldCount, getFieldName, getFieldValue and getFileHash. This allows us to retrieve archived items we have stored on the Ethereum network.
Taking it further
The functionality described here is very basic and there are a number of areas which require improvement:
– Multiple calls to the same method are required to retrieve all field names and values. This is very inefficient, especially on a decentralized network. Instead, information such as metadata should be returned in a single call, reducing the traffic between our web page and the Ethereum network,
– The contract is hard coded. Preferably we would want to be able to specify any contract.
And finally, we would we would ideally want to be able to pass the contract address from some kind of list page. This would require some kind of data store of contract addresses. We have a few options here which would need to be implemented when the contract is created. The simplest solution would be to store the contract address in a relational database such as MySQL or MariaDB. Alternatively, since this is a decentralized application, we may want to investigate using a decentralized database, for example, OrbitDB. There are also some promising developments using the Ethereum Name Service (ENS).