Distributed Web with IOTA: a technical overview
The full article was originally published by Patrick Jusic on Medium. Read the full Article here.
IOTA is the distributed ledger for the Internet of Things. Here at Things Lab we try to find out solutions based on this technology in order to enable the rise of IoT devices with a secure infrastructure.
In this post I am not going to talk about how we could use IOTA to build the internet of Things but whether we can use IOTA to build a distributed Internet.
First we need to explain what we mean by distributed internet, then I am going to do a fast dive in IOTA transaction architecture and IRI node to show how we could use them to serve a distributed internet. Later I will share some code and solutions on how this could be managed by reporting some benchmarks and finally the drawbacks this approach would lead to.
In our minds the concept of distributed internet takes shape as a way to retrieve a web content not taking into account who serves it.
This concept applied to IOTA starts from the premise that we are able to serve a web page querying for a transaction. In particular, we could store a web page in a transactions bundle (I will specify the structure later), and serve it extracting the data from the bundle. We are talking about a transaction published to the IOTA network, hence a distributed piece of data. Starting from the assumption of the availability of this distributed data, and I am going to show how to store them, we need a distributed way to serve them.
We base our concept on available technologies. We don’t want to replace the HTTP protocol or anything like this. We should be able to use a simple open link web browser to ask for a domain name and receiving back a web page content.
Currently, to retrieve a transaction from the Tangle, we have to go through the IRI node, using the JSON RPC interface via the command line or using one of the API implementations. This operation implies the need of a web server able to listen for the request, where reasonably it should find the bundle hash, and retrieve the transaction through an HTTP request, extracting the content and sending it to the client specifying the Content-Type as text/html. This would work, but this is obviously not a distributed way to serve the web page.
Now let’s dive in the technical aspects to understand how this mechanism could be built.
From the IOTA docs:
A transaction is a single instruction to credit IOTA tokens, debit IOTA tokens, or send a message. To transfer IOTA tokens, you need both input and outputs transactions, which are packaged together in a bundle.
Hence transactions are always packed in a bundle. I won’t paste here the entire page of the documentation (you can find the link in references below). What we care regarding transaction structure itself is that an input transaction contains a signatureMessageFragment, that is where data and the signature are stored. The signature length is based on the security level of the address and a security level higher or equal to 2 produces a signature too large to fit inside the signatureMessageFragment field. Hence commonly we will have more than an input transaction in a bundle, in consequence of the length of the signature.
Although is recommended a maximum of 30 input/output transactions, there are no limits about the number of transactions, so we can exploit the signatureMessageFragment to store data we are interested in. In our case we can store our web page in this field. Therefore if we want to retrieve and render the web page we have to extract this field from each input transaction, concatenate them and extract the data slice (remember that this will be stored as a string of trytes, but we have the utils function trytesToAscii to overcome this).
Take into consideration an easy webpage with a dozen of html tags and some dependencies. This web page after being minified a uglified will weight around 250kB, that means around 230 transactions, considering that an input transaction can contain a message of 1.5kB length. At first glance, one would question how long would it take to attach 250 transactions, or even execute the PoW for each of them.
Well, luckily we used a little FPGA hardware accelerator module using the Pidiver library (thanks to Thomas for supporting us, link in references) and we were able to attach the bundle to the Tangle in around 1 minute. Precise benchmarks in the last paragraph.
This is the code we used to accomplish it. As you can see is the same code of the Pidiver tutorial but I read the message from the file example.html:
As previously stated we would need a distributed way to serve the web page that without the fetching of a bundle through a web server able to retrieve, parse and return it.
As you can guess this would be an important step to serve web contents in a distributed way, in particular if these functions were to be a default function in the IRI implementation. The last step we miss here is a distributed DNS able to redirect the request to one of the nodes that expose this function. Such services already exist and this functionality can be easily achieved using a failover or a load balancing strategy.
At this point we have traced the line to be able to realize what we have in mind, but now we face a big limitation in the IRI node implementation. Currently it is only possible to reach one of the endpoints exposed from the node through an HTTP POST request, specifying the command in the body of the request. Obviously this is a big limitation because web browsers execute a GET request when they need to retrieve a web page through a certain URI.
This limitation disrupts our plans and we plan to submit a pull request to the IRI node repository to enable this feature, e.g. expose some commands via a plain GET request, just based on the URL.
In this moment we are not able to overcome this limitation hence our tests are based on a centralized approach on the backend, using a classic client server architecture, but we are confident that this new features would produce similar results. Our tests are based on a NGINX web proxy backed by an Express NodeJs web server.