In our recent post, we highlighted our achievement regarding the release of an on-chain version of uniris.io - our website. We explained why we delivered this milestone in our roadmap for the alpha network and it is a game changing. Today I present a more technical point of the implementation of the website hosting.

Website components

Any website contains different kind of assets such HTML pages, CSS, Javascripts, Images, etc. ...

Currently our website contains:
- HTML pages (for different translations)
- CSS (vendor libraries and custom ones)
- Javascript (vendor libraries and custom ones)
- Images (PNG, SVG)
- PDFs (YellowPaper, WhitePaper)

uniris.io web assets

You can see on the image below that our page is composed of many different assets including vendor libraries which are not described in the image.

When you are committed to build a real decentralized website, you need to consider which assets will be on-chain and how. This mostly relates to the vendor libraries and your own custom made development.

Hosting strategies:

Different approaches are possible to host them on-chain:

  1. Create a single html page by "inlining" all the assets: Convert all the images into base64 encoding, inject javascript on the bottom of the files concatenated and minified. This approach looks fine but may raise some issues:
    • The HTML page may become excessively big, which may result in a high transaction fee and it may be limited by the network to avoid congestion of the transaction mining
    • Since, the vendor libraries are injected into the page, any vendor libraries updates would be complex to manage. Also the website transaction chain will have to change for such feature updates.
  2. Using transaction chain of vendor assets and a single page HTML transaction with your development (inline CSS, Javascript and base64 images). This approach fares better in terms of vendor libraries maintenance and single responsibility principle, but may be difficult to maintain your own development.
  3. Using transaction chains for vendor assets and your own Javascript and Stylesheets while maintaining the HTML page and images inlined as an unique transaction. This provides the facility to make changes in your code without involving redeployement of your HTML page.

For us, we decided to use the last approach, with different transaction chains for HTML page, vendor libraries (CSS, Javascript), custom CSS, Javascript files and PDFs. The images are either in-lined in SVG or base64 for PNG/JPG format.

To be able to in-line some of the content, manual or automatic process can be used such as Grunt or Gulp which are toolkits to automate and enhance web development workflows.

Vendor libraries on-chain ? What is the purpose ?

We wanted to show an example of the decentralized and incentivized web developments shared across a secure P2P network.

For now, we deployed transaction chains for Bootstrap (CSS Framework), jQuery (JS framework) but the end goal is that the true developers and maintainers of the project will host their own content and make it accessible through a Blockchain network.
The point is also to facilitate the reward mechanism and involve the developer community in our network as much as possible.

This will also benefit any website depending of those libraries and will get the latest "stable" version, thus making it up to date instantly without further development or deployment. Note: if for security purposes, you don't want to get the latest one, it is possible to link to a specific transaction on the chain - aka specific version.

And what about fonts ?

This is a pertinent question regarding web assets. Many websites and CSS libraries are using fonts for text, icons and often they are loaded as external assets. So, to be able to embed those fonts into your website or your library, an base64 encoding of the fonts is required in such format:

@font-face {
  font-family: 'MyFont';
  src: url("data:font/woff2;base64, <<base64 encoding of the font file>>")

Using other font formats is possible such as EOT, TTF, WOFF, and WOFF2

Node content delivery

To support such behaviors and features, every Uniris node has the capability to deliver content for any transaction, using our storage election algorithm.
Hence, we developed an API / Endpoint to deliver transaction content efficiently.

Content delivery endpoint

GET https://blockchain.uniris.io/api/last_transaction/{transaction_address}/content

We designed the endpoint to retrieve the latest transaction on a specific chain giving the last fresh information about your asset. This point is crucial to prevent any additional developments and deployments when a depending asset has changed.

By default, this endpoint will deliver the content of the last transaction given in a raw format. However, browsers often require a type of content to be able to interpret it correctly, such as stylesheet, pdf, json, etc.
For that, we added a parameter to support mime type.

For example:
To deliver a CSS stylesheet, will requires the mime: "text/css"

<link rel="stylesheet" href="https://blockchain.uniris.io/api/last_transaction/{transaction_address}/content?mime=text/css" />

And if you want to display a PDF like our Yellow Paper or White Paper you will want to use the mime: "application/pdf"

<a href="https://blockchain.uniris.io/api/last_transaction/{transaction_address}/content?mime=application/pdf" target="_blank">MyPDF</a>

So on and so forth...

Performance criticality

When we are talking about content delivery in technical details, the main point is the data must be fetched as fast as possible depending on the geographical position , wire optimizations, etc.

For this purpose, every Uniris node and thanks to the storage node algorithm and beacon chain, is able to fetch data from the nearest node using network coordinates.

TLDR: Network coordinates are way to establish distances between nodes in a P2P network using latencies to estimate and improve the data retrieval.

Moreover, we are leveraging two caches mechanisms:

  • Browser cache: capability to avoid reloading the same asset if it has not changed. Instead of using a Time-To-Live cache mechanism we are using an ETag representing the last transaction address of the asset. If the assets were downloaded previously and if the transaction address (ETag) doesn't change, the browser will use its cache to retrieve the content. Otherwise, the new version will be retrieved.
  • Storage cache: before leveraging storage node algorithms and forwarding to the relevant storage pool for the last transaction of the chain, every node will lookup its transaction storage cache, to find out if it has the transaction stored. If so, the transaction will be returned as fast as possible without involving any I/O seek operations. Otherwise, the data will be downloaded by requesting the right storage pool.

And finally, to enhance the data retrieval for web performance, the content delivery endpoint will compress the data using gzip algorithm so the browsers will be able to support and decompress the data to reduce costs of data transmission.

Analysis of: blockchain.uniris.io

Network frames of the asset retrieval for blockchain.uniris.io

~3 sec: not so bad for a large website stored on a decentralized P2P content delivery network on top of Blockchain involving requests for  24 transaction chains.

We can see on the image, that a few CSS assets are downloaded using transaction chains while some are in-line embedded such as images (data: image/png  => data uri using base64 encoding).

blockchain.uniris.io transaction chains files

You can see on the image above, coming for GitHub, that blockchain.uniris.io is using quite a few transaction chains to deliver the website without having too much trouble in terms of performance and development. The advantage of using a Blockchain and secure P2P network is the transparency and verifiable authenticity. Take a look at our explorer to find out and check that those transactions are really live and cryptographically validated.

https://blockchain.uniris.io/explorer/search?address=00CCB0371A3CA0775B73B0E9DE5175609411C1E470AF92F689A6E1B4F1DEF6C5C2&latest=true


You can stay informed and contact us by following the links:

You can stay informed and contact us by following the following links: https://uniris.io
Uniris Community on LinkedIn
team@uniris.io