Introducing RISE v2
By: Andrea Baccega
Tags: Blockchain, Typescript, Cryptocurrency

2018 was a very productive year for RISE. Let me recap some of the achievements the team was able to deliver during 2018:

Along with all these updates, I started working in a private repository to create the new RISE v2.

Why v2

New v2 is built to have the following concepts in mind

Extensible Modular Simpler More flexible

The ones above are the 4 core features that I think were lacking in the old v1 codebase hence why I started the rewrite.

What’s new in v2

RISE v2 hosts several new improvements. Let’s start from the biggest change:

RISE Modules

Thanks to yarn and Lerna we were able to rewrite all main RISE functionalities separating the concerns of each module.

This is not only a nice coding approach allowing to re-use components but will also allow third-party developers to override core modules by injecting their own replacing module.

For example, there is a “consensus-dpos” module which provides all the code needed to handle the DPoS rules and API; If a developer wants to, they might write their own consensus module and re-use all the other core modules.

You can think about modules like pieces of a puzzle. As long as your piece has the same shape as the “original” one, it will fit nicely creating a different picture.

More info about modules here.

Modules LifeCycle

Since every module is an (almost)-self-contained piece of software it needs to follow a contract, or a so-called interface, in order to be a valid module.

Module developers can also benefit from using the lifecycle declared within the above-mentioned interface. This is beneficial especially when modules need to initialize or teardown specific elements within their logic.

The main 4 lifecycle events are (in order of execution): preBoot, boot, teardown, postTeardown.

Modules can also override the configuration of other modules as well as adding specific commander options when booting the application.

Modules resolution

DAG — Source: Wikipedia

Since Module ‘A’ could depend on ‘B’ a Directed-Acyclic-Graph is built on-startup so that the lifecycle and config override respects the expected natural flow.

This also ensures that no 2 modules reference each-other (either directly or non-directly) leaving the codebase clean as well as making sure that different boot produces the same result in term of booting priority.

Since I follow (as much as possible) the KISS principle, modules can declare that they depend on another module by exploiting the ‘package.json’ capabilities that Node.js developers are already used to.

Technology upgrades

The underlying technology of the RISE core needs to be constantly updated to leverage both performance and security improvements.

With this in mind we decided to update:

Node.JS from v8 to v10;

TypeScript from 2.8 to 3.4.5;

PostgresSQL from 10.4 to 11.3.

We then decided to remove Redis entirely as it was no longer used in the codebase and there was no real reason to keep it as third-party dep.

The WordPress-like Hook System

If there’s something great about WordPress is its the plugin and hook system. Since one of the main assets of the whole WordPress ecosystem is the wide variety of plugins that are installable it seemed a good idea to copy the good concepts and bring them, for the first time, in the BlockChain eco-system.

In RISE v2 we use “mangiafuoco”, a Node.JS library written by me that mimics the WordPress hook system by adding utility functions.

Embracing this technology was kind of the next step when building a modular core since it allowed us to decouple modules inter-communication enhancing by several factors the maintainability and code clarity.

To enhance and smoothen out the learning curve we even created TypeScript Decorators which you can apply on your methods. This will give you type-safety, the thing we all love about TypeScript.

Example of multi-hooks usage.

Of course, all filters and actions are declared in the “hooks” directory of each module allowing every developer to easily find exported actions and filters.

Execution priorities you ask? We also support that and you can use it as well :).

New Transaction Types and functionalities

V1.x Transaction system has several design flaws and is not as flexible as I wanted it to be.

The new tx schema has the following benefits compared to the previous version:

Streamlined serialization and deserialization

Ability to encode different address systems (more on this later)

Unequivocally encode-decode payload

Before this update, we had several constraints and, for example, the Ledger Nano integration was painful to code and test.

The new tx schema opens a lot of new possibilities for RISE enabling the amount of flexibility we need to satisfy almost all use cases.

Another nice side-effect of the new transaction types is that they do natively support having dynamic fees. Even if RISE does not necessarily need dynamic fees now, we always need to anticipate needs to avoid unnecessary network bottlenecks.

The new Send transaction type has a new field that can hold up to 128bytes of raw data

Send transaction with “banana” string encoded in the payload

This opens up a lot of new possibilities and scenarios developers could use to permanently store data in the RISE blockchain. EG: An eternity wall, a payment processor, a notary system, …

Arbitrary precision library with bigint

In v1 we used BigDecimal javascript library which has been a great resource against very-well-known javascript issues when handling math.

It’s very crucial that the math is bullet-proof unless you are a fan of Thanos and its snap and wanted to see it applied to the blockchain :).

With v2 we leverage “bigint” which provides integers with arbitrary precision with blazing fast (native) speed.

So, by switching to this new feature, we got rid of a third party dependency (which is always a great thing) and we leverage native speeds when dealing with big numbers.

Introducing RISE address v2.

The “oldy” addresses look like “12345678R” while this might sound great as only numerical digits are used, the way the address system was initially designed comes with 2 coupled security flaws:

Address space is “only” 2⁶⁴. (compared to 2²⁵⁶ public-key space) 2 public keys can result in the same address. (collision attack)

Along with the 2 issues above, the current RISE address system does not allow any data encoding so it’s basically impossible to have special addresses with a different purpose.

Let’s get straight to the point. What does the new Address will look like?

rise1q8gsvlw985fvx22me8mhnvpwhfzf4dkehzt5nq84mk35zup2prfs73z5ydg

“OMG, that’s long… What are the PROs?”

State of the art technology (borrowed from Bitcoin — bech32), flexible, has checksum!!!! Meaning that if you had to type a long address and made up to 4 mistakes we would be able to find exactly where the error was made, by far more secure, QR code efficient — easier to read.

Along with all the goodies, we are making a big change in the way the 2 address system will co-exist.

Since V2. The primary account key will no longer be publicKey while rather the address itself. Since V2 is, by far, more secure than the previous address system, we will discourage using V1 by highering the TX fees when sending/receiving.

New P2P Comm Layer (Again)

Since ProtoBuf we basically solved most of the p2p bottlenecks. Unfortunately, some minor errors were made when designing the new p2p layer back then.

The new P2P layer features:

Same Transaction Per Second output Same Bandwidth efficiency More flexibility More robustness

Let’s focus on the third and fourth elements above:

The P2P layer has been decoupled and is now a separate module (“core-p2p”) which allows third-party devs to deploy their own p2p solution. Ex: just for fun a developer could use morse-signals over the infrared spectrum to send/receive data to/from neighbor nodes.

About Robustness: we designed the p2p classes to be easy to use and rock solid. The p2p layer will treat your data as an opaque message to be sent and received, serialization and de-serialization are up to the developer. Multiple codec technologies might co-exist; for example, a module could register a p2p endpoint for sending/receiving data in “plain-text” and another could use binary or ProtoBuf as the encapsulation method.

Furthermore, requests can now be batched and also eventually expire. Handy for many use-cases.

Last breaking change for the RISE v2 would be the communication ports. In RISE v1.x we used the 5555 (or 5566) port for both public APIs and internal consensus communication. In V2 we decided to separate the 2 comm channels:

Port 5554 for consensus communication;

Port 5555 for APIs.

This small change will improve even further the performances of the communication layer by removing the API bloatware from the consensus endpoints.

Deprecating MultiSignature Accounts

This might sound like a step back, right? No more multisig accounts… WhatTheHeck??

Well, there are 2 reasons behind this move:

The multisig functionality was, to say the least, over-engineered and poorly conceived (both in code and database) The new Address system is able to encapsulate multisig accounts such as in BTC.

Note: you can’t really create multisig accounts in v2. (they’ll come soon™)

To summarize, we removed a big chunk of codebase (and tests) that no-longer needs to be maintained :).

In RISE we also have second signature accounts. That functionality will be maintained as a separate module named after its functionality (core-secondsignature). We decided to keep this feature since many accounts were actively using it compared to multisig which was not used at all.

Changes to the consensus (Again)

Improving current solution is crucial. That’s why we decided to stop distributing fees evenly to all delegates. “Wait what”?

In v1 : All tx fees were collected and evenly distributed to all delegates who participated in the round.

: All tx fees were collected and evenly distributed to all delegates who participated in the round. in v2: delegates will be rewarded the fees they forge.

In all honesty, the “v2 way” should have been “the way” as it provides an incentive for delegate nodes to keep their node up&running with proper networking.

The Database

Since RISE v2 is, besides many other things, a big refactor of v1.x, it was about time to change the Database structure to a more meaningful schema.

A bunch of columns was removed from the accounts table and, at its base form, only 4 (vs over 10) column are needed.

Furthermore, tables and some columns were properly renamed to follow a single standard convention.

Idempotent DB Update Scripts

Upgrading a blockchain isn’t as easy as you might expect. Database updates are no exception. In RISE v2 we decided to create “schema.sql” files which basically are idempotent. But what is idempotency? From wikipedia:

Idempotence is the property of certain operations in mathematics and computer science whereby they can be applied multiple times without changing the result beyond the initial application.

(wikipedia)

With this change of approach we now have the ability to:

Keep the current, most-up-to-date, database schema in a single place for easier maintenance and debugging.

run the schema.sql upon each startup and make sure we don’t break anything

How/When will the update happen?

Since the p2p layer is no longer backward compatible we’ll provide an update script that will take care of upgrading the blockchain core at a specific point in time (or better said, in height).

All node operator will need to trigger the update script before the deadline to keep their node(s) synced with the network. Delegates failing to do so will be eventually banned by the consensus leaving space to worthy delegates that updated instead! (more info).

Of course we’ll give it a go using testnet first that has been rebooted a couple of weeks ago to have the same features and configuration we have in mainnet.

If interested, please join our Slack, and enter the #testnet channel to receive some testnet tokens to play with and instruction on how to set up a node.