IOTA Transactions

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.

PiDiver V1.3

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:

Code to load a web page in a bundle of transactions

IRI Node

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.

One of the last features of IOTA are the IXI modules. IXI modules enable everyone to enhance the IRI’s exposed API adding custom commands. In particular it is possible to create a function (using Java o Javascript) and insert it in the node folder in order to make the node execute it when the specified endpoint is queried. We start from the assumption that IRI should be as fast as our web server to retrieve and return the transaction. In this way we could have a set of nodes able to receive a call passing a bundle hash and returning back the content of required transaction.

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.

We registered the iotaweb.site domain in such a way to redirect the request to our web proxy. The temporary replacement to simulate a GET request directly to the node exploits a simple condition in the Nginx configuration file (line 20):

Nginx location block in configuration file

As you can see the request is redirected to out express web server where the request in handled like this:

Router endpoint to handle get request

You can see that the content is returned setting the Content-Type header to text/html to inform the browser that we are returning a web page and that he should render it. In the business logic the getTx method just fetches the bundle based on passed id and parses the result as previously explained:

Module to fetch the bundle and extract the data

In the last technical part of this article I am going to show you the results we obtained.