The Wallet Misadventures
Several attempts have been made to find the right framework for the future Unigrid wallet. We discuss the challenges, advantages and disadvantages of the different attempts.
I thought I'd take a moment and update the community on what's happening on the development front. This post might be slightly technical - so I hope you like getting into the weeds.
As you might already know, The Unigrid Foundation has joined the next top blockchain startup hackathon hosted by GDA Capital. Attending this hackathon will give the foundation a little bit of exposure and allow us to show the judges of the hackathon what we're all about.
If time permits, our plan for the hackathon is to demonstrate a demo of our anonymous Internet access. On top of everything else, this paves the road for a very busy summer! To be able to accomplish this, a number of things need to be implemented in our code base first:
- Janus Java needs to be completed and released - The old QT wallet is clunky, slow and complicated to use. Rather than going the route of most other cryptocurrency wallets, we aim to make our wallet as easy and simple as possible. The current learning curve for using cryptocurrencies is way too steep. If we want global adoption, everything needs to be easy to use.
- Implement a Java bridge to the code base of the daemon - We intend to create binaries with GraalVM and LLVM. This will allow us to mix compiled Java code and C/C++ code in the same native binary. Most of the new code written will be done in Java, with some optimizations in C++ on top (if needed).
- Implement SOCKS proxy server - The daemon will expose a socks proxy server that users will be able to redirect connections to. This will allow current legacy applications to use the Unigrid network to access the Internet anonymously.
Selecting the right framework for the wallet
We have gone through several iterations and considerations when selecting the framework for our future wallet. Many of you are even running our alpha release of the Janus Electron wallet as your main Unigrid wallet (also lovingly denoted as our super-duper-alpha wallet). This wallet has also been extended to support the Cypherium project via the Janus Cypherium project.
First try: Electron and ReactJS
As stated above, our first attempt at a new wallet was to use the ElectronJS framework together with ReactJS, originally based on the work by the Swipp cryptocurrency. While it certainly works, Electron and JavaScript in particular present a number of limitations and problems:
- Horrible code with JavaScript promises and bad design - The way most API calls work and the single-threaded design of JavaScript creates a messy code base that is difficult to maintain.
- Many JavaScript APIs rely on monkey patching - Rather than being designed with extensibility in mind, many JavaScript libraries rely on monkey patching. One library patches another with dependencies that again rely on monkey patching, creating an endless mess where security and maintainability is thrown completely out the window.
- Unreasonable memory footprint - Electron fires up NodeJS and an isolated instance of the Chrome browser together with a plethora of JavaScript libraries and dependencies. The memory required by the wallet ends up anywhere between 400-700MB which seems unacceptable for just a graphical interface.
Second try: JavaFX, Spring Boot and PrimeFaces
In our second attempt, we wanted to see if we could make an equivalent solution to Electron in Java. We made a functioning proof-of-concept based on JavaFX, Spring Boot and PrimeFaces in order to see what kind of performance, startup time and memory footprint a solution based on these technologies would yield.
By using OpenJ9 (a Java runtime from IBM and The Eclipse Foundation), we were able to bring the memory footprint below the ElectronJS solution. However, it was still using 300-700MB of memory. There are several reasons for this:
- Spring Boot has many dependencies - The framework has many dependencies on external libraries. Furthermore, the more Spring Boot libraries you add, the worse it gets. When adding JoinFaces (for JSF and PrimeFaces compatibility) it quickly becomes even worse.
- Tomcat is a memory hog - Just like in the ElectronJS and ReactJS case, running JSF and PrimeFaces requires a running web application server. The default one for Spring Boot is Tomcat and it consumes quite a bit of memory.
- Requires JavaFX WebView - While it's certainly not as memory intensive as running a sandboxed Chrome browser like in the ElectronJS case, this solution still requires the web view extension of JavaFX. Being a full webkit implementation, it still requires a pretty big amount of memory to run.
This solution is better. It allows us to write cleaner code. However, it's not quite what we want. The memory footprint is still too steep and the startup time is just as bad as when using Electron.
If you are interested in taking a look at this solution, it has been archived away in a separate branch of the Janus Java repository.
Third try: JavaFX and Weld (CDI)
Our last and hopefully final attempt strips everything down to a pure JavaFX and Weld (CDI) solution. CDI stands for Contexts and Dependency Injection. Being part of Jakarta Enterprise, it is the standard Java library for handling dependency injection in enterprise Java applications.
This third attempt retains much of the code from the second attempt but strips things down and removes all the JSF and XHTML code. Instead, we use Scene Builder to define the graphical interface, defining FXML files. This moves the whole interface to JavaFX and to the use of JavaFX components.
Using OpenJ9, this final attempt pushes the memory footprint down to a usage of around 100-150MB. At the same time, startup times are nearly instant. This presents a significant improvement and clearly shows that a solution based on just JavaFX is the way to go. As the screenshot demonstrates, the framework also allows for skinning capabilities that equal those of HTML5.
Following development
If you want to follow the progress and development of Janus Java, please refer to the official GitHub repository on The Unigrid Foundation GitHub project page.