Planetarium Engineering Snack

What's new in Libplanet 0.11–0.19


Hello. Long time no see. Libplanet1 has released several minor versions over the past few months. However, as our release policy and cycle changed, and as we had responded to deal with diverse problems on the mainnet of our first game Nine Chronicles, powered by Libplanet, we’d been unable to keep up with the updates. So let’s focus on some of the key changes that have been made in between the past releases.

New Release Cycle

Previously, Libplanet had no clear rules for its release cycle. It was just simply giving a new version number to a collection of unreleased changes when there is a big API change, or some time has passed since the last release.

However, since the launch of the Nine Chronicles' mainnet last year, Libplanet has had to make frequent releases to fix various problems in the mainnet. Currently both teams of Libplanet and Nine Chronicles in Planetarium work closely together to catch up each other’s updates. This release cycle of Libplanet is likely to continue for a while.

Under that policy, there have been 9 minor releases in the last few months, from 0.11.0 released in March 2021 to 0.19.0 released this week:

Protocol Versions

Added in version 0.11.0.

A protocol version is a property of a block that represents the version of Libplanet used for mining. It helps games powered by Libplanet to easily upgrade the Libplanet version, and on the Libplanet side, it allows us to add new functionalities without breaking backward compatibility with existing networks.

API-wise, it is exposed through the Block<T>.ProtocolVersion property, which is a 32-bit integer. Those numbers solely represent a version of the network protocol, which is distinct from a version of the library package (on NuGet Gallery). In compliance with Semantic Versioning, patch releases will never increase the protocol version, but only minor and major release can increase it.2

As of Libplanet 0.19.0, the current protocol version is 2, and any blocks produced before Libplanet 0.11.0, which did not have a protocol version, are treated as the protocol version 0.

Network Transport Layer

Added in version 0.11.0.

Since its inception, Libplanet has left much of the low-level networking to NetMQ, which is a .NET implementation of ZeroMQ. However, we’ve now determined that it is necessary to change its networking layer to not fully rely on NetMQ so that Libplanet can be used on various platforms such as mobile and Web.

We created the network transport layer to meet those demands. We added this abstraction layer experimentally to diversify low-level network transports and to allow game developers to define and use them to meet their own requirements.

API-wise, it is represented as the ITransport interface, and the NetMQTransport which implements it is built-in.

As it’s in a pilot phase, the interface still has been adjusted through several minor releases, and game programmers can’t yet use their own transport implementation. Later in the year, Swarm<T> instances will be configurable with custom transports besides the new TCP-based transport, which aims to replace the NetMQTransport.

Configurable PoW Hash Algorithm

Added in version 0.12.0.

Previously, Libplanet had used SHA-256 for proof-of-work. However, since version 0.12.0, each network can configure its hash algorithm for PoW by implementing its IBlockPolicy<T>.GetHashAlgorithm() method. As it is not only configurable for each network, but also for block indices, it can be migrated within a network after its establishment.

You can use any hash algorithm for PoW as long as it is a subclass of the HashAlgorithm abstract class, which is built in the .NET runtime. Since the hash algorithm is not necessarily required to be included in the .NET runtime, you can use your custom implementation as well. For instance, RandomXSharp, a .NET binding library for RandomX we made, also provides a subclass of HashAlgorithm.

The following code shows an example policy requiring blocks below 10,000th block to use SHA-256 and above blocks to use SHA-512 within a chain:

HashAlgorithmType GetHashAlgorithm(long index) =>
    index <= 10_000
        ? HashAlgorithmType.Of<SHA256>()
        : HashAlgorithmType.Of<SHA512>();

Non-blocking Renderers

Added in version 0.14.0.

IRenderer<T> and IActionRenderer<T> interfaces, event listeners that wait for state transitions of node’s local chain, do not spawn new threads but flow in a blocking manner. Suppose some rendering logic calls Thread.Sleep(60_000)—continued state transition from it on the chain will be made after waiting for 60 seconds of rendering.

Since version 0.14.0, we’ve introduced two decorators which execute time-consuming rendering logic in a separated thread without blocking– NonblockRenderer<T> and NonblockActionRenderer<T> classes. Both classes take another render through their constructors, and call its event handlers in a separated thread. As they are decorators, the existing renderers can be transformed into a non-blocking style, by wrapping existing ones with the decorators.

Although they are non-blocking, they have their own internal queue to guarantee the order of events.

Configurable Transaction Preference By Miners

Added in version 0.17.0.

The Libplanet protocol does not require miners to have any priority for transactions to include in a block, as long as the IBlockPolicy<T>.ValidateNextBlockTx() predicate method is satisfied.3 However, if there are too many transactions to be included in a block, a miner may need to prioritize them so they are chunked into multiple blocks.

Since version 0.17.0, instead of Libplanet arbitrarily prioritizing them, miners themselves can configure the priority for transactions to include in a block. API-wise, BlockChain<T>.MineBlock() method has the txPriority option which takes an IComparer<Transaction<T>>.

Blocks Signed By Miners

Added in version 0.18.0.

Since protocol version 2, i.e., Libplanet 0.18.0, every block is signed with the private key of its miner, and it includes the public key as well as the address of its miner.

API-wise, block signatures are represented as Block<T>.Signature property, and miners' public keys are represented as Block<T>.PublicKey property. Blocks with protocol versions 1 and 0 fill both properties with null.

Multi-Threaded Mining

Added in version 0.19.0.

Since Libplanet 0.19.0, each block is mined in parallel, depending on the number of CPU cores. The option to configure the number of processes (workers) will be added in the future.

Many Others

In addition, lots of new features have been added, and it has significantly stabilized the network in many areas, solving problems that have arisen during the past few months of the mainnet ops. Please check the entire changelog of each release for details.

If you are interested in Libplanet, please give it a try. As we are always in our Discord server, feel free to ask any questions if you have one!

  1. Libplanet is a common library that abstracts out the implementation details of decentralized multiplayer gaming such as peer-to-peer networking and data synchronization. ↩︎

  2. This does not mean that all major and minor releases increase the protocol version. In fact, most releases do not increment the protocol version. ↩︎

  3. Of course, there is an order between transactions signed by a signer. These are ordered by Transaction<T>.Nonce↩︎