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:
- 0.11.0 (March 30)
- 0.12.0 (July 23)
- 0.13.0 (July 28)
- 0.14.0 (August 5)
- 0.15.0 (August 18)
- 0.16.0 (August 25)
- 0.17.0 (September 28)
- 0.18.0 (October 13)
- 0.19.0 (October 27)
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!
Libplanet is a common library that abstracts out the implementation details of decentralized multiplayer gaming such as peer-to-peer networking and data synchronization. ↩︎
This does not mean that all major and minor releases increase the protocol version. In fact, most releases do not increment the protocol version. ↩︎
Of course, there is an order between transactions signed by a signer. These are ordered by
Transaction<T>.Nonce
. ↩︎