A History of Minter Blockchain Development

Website: https://minter.network

GitHub: https://github.com/MinterTeam

Hi, everyone! This is Daniil Lashin, the lead developer here at Minter. Back in 2017, we — a team from DeCenter — had an idea to design a blockchain that would allow any user to create 100% liquid coins in a couple of clicks. Such coins would enable users to instantly buy or sell any volume at a market price and without the need to turn to exchanges or similar services.

For over 18 months, a team of seven developers has been working on the Minter ecosystem. Now that the mainnet launch draws near, I am writing this article to give you a little insight into the general architecture and logic of the network operation, as well as to provide the reasoning behind making particular decisions.

Choosing a Framework

Creating a blockchain from scratch is a challenging and time-consuming process. It requires large teams of developers and years of work. P2P communication systems, a consensus algorithm, and many other typical blockchain modules have to be built anew. We did not have such capabilities at the time, so we decided to take a ready-made solution and start from there.

When we were selecting a base to build on, we considered the following projects:

Ethereum

The first blockchain we came up with was Ethereum. The main node is written in Go, which is considered one of the fastest programming languages with a low entry threshold. It is easy for the community to audit the code, and for the team, to find new developers.

Advantages:

Disadvantages:

Graphene 2.0

Graphene is a technology that lies in the foundation of various blockchains (Steem, BitShares, to name a few). Graphene 1.0 with its throughput of hundreds of thousands of transactions per second was a real breakthrough.

Advantages:

Disadvantages:

Tendermint

Now we have finally come to the framework we eventually chose, Tendermint from Cosmos.

Based on the DLS protocol, it does not require any “active” mining — as is the case with Proof-of-Work — and can ensure the secure operation of the network provided there are more than two-thirds of “honest” actors.

Advantages:

Disadvantages:

Hello World

Tendermint is responsible for the generation of blocks, peer-to-peer communication, and reaching consensus. All of it helped us skip these stages of development and focus on the main thing, the business logic of our blockchain.

We decided to use Ethereum’s developments for addresses, cryptography, and data storage. There were many libraries for different programming languages (Golang, Swift, Android, Javascript, PHP) and platforms (Web, iOS, Android), which allowed us not to develop them manually and release applications and wallets as soon as possible.

Tendermint was surprisingly easy to use, so we were able to create a proof-of-concept in a few weeks and make the first transaction on the Minter network. It performed a very simple function: sending coins from one account to another.

The first transaction on the Minter blockchain

But even after conducting the first transaction, we were still faced with many architecture issues. Among them:

General Network Specifications

Experiments and calculations led us to the following parameters of our blockchain:

Coin Creation

To create a coin on Minter, one needs to send a single transaction — CreateCoin.

CreateCoinData {
Name
Symbol
InitialAmount
InitialReserve
ConstantReserveRatio
}

The cost of creating a coin depends on the number of characters in a ticker symbol:

The creator should also have the amount of initial reserve on their balance, which must be more than or equal to 1,000 BIP.

To prevent the network from being flooded with “dead” coins, we decided to introduce the clean-up mechanism. The coin is deleted if at least one of the following conditions is met:

In these cases, all coins will be removed, and reserves will be proportionally refunded to the users.

An example of creating a coin in Minter Console

Liquidity of the Coins

The creation of a new coin is possible only if it is backed by BIP, our base currency. This backing approach has allowed us to create what we call the network of liquidity as one can instantaneously and limitlessly exchange any coin for any other one. Such operations are executed with the use of math formulas introduced by economist John Keynes and kindly modified by the Bancor network.

To issue a coin, the creator has to first determine its parameters. For a better understanding of the very process, let us assign the following settings to our coin:

CRR (Constant Reserve Ratio) reflects the volume of BIP reserves backing a newly-issued coin. The higher the coefficient, the greater the reserves and thus the lower the volatility. And vice versa.

Initialize the creation, and you will have a brand new coin. Let us call it NewsCoin.

In our example, after the transaction, founders will have 2,500 NewsCoin for which they in average paid 100/2,500=0.04 BIP apiece. Since the reserve amounts to just 40%, the price will increase to 0.1 NewsCoin/BIP according to the formula. Yes, because the reserves are not full, the price of each new coin is a bit higher than that of the previous one, which is one of our fundamental ideas.

If you think that one may now finish the ICO by selling coins back for BIP and make substantial gains, I will disappoint you — the formulas work in both directions, and by burning (selling to the system) 2,500 NewsCoin, one will receive the initial 100 BIP. Look at the graph; everything is pretty simple.

You can try out the mechanics in the calculator that simulates the buy and sell operations: https://calculator.beta.minter.network

Formulas were rewritten in the Go language. You can check them out in our repository: https://github.com/MinterTeam/minter-go-node/blob/master/formula/formula.go

And everything would be all right if not for the fact that only integers can be used in blockchains. It is necessary because different CPU architectures treat floating point numbers differently. And for the blockchain to work, the calculations must be deterministic and unambiguous on all devices.

All balances that you see in your wallets are results of their division for better display. In Minter blockchain, 1 coin (BIP) = 1,000,000,000,000,000,000 base units (pip).

Therefore, the biggest problem we encountered was the complexity of these formulas for deterministic (identical for all devices) calculations. Since formulas use raising to a fractional exponent, we had to go for the trick — the big.Math library from Golang developers enabled us to convert big.Float into big.Int and back and made it possible for us to perform such calculations quite unambiguously.

Economics of the Network and Block Rewards

We believe that the majority of the coins on the blockchain should be mined, and not sold at an ICO. Therefore, users will receive 98% of the total supply as block rewards.

The block reward starts at 333 BIP and will be decreasing gradually over seven years. You can see the corresponding formula in the source code: https://github.com/MinterTeam/minter-go-node/blob/master/core/rewards/rewards.go

Coin issuance schedule

Types of Transactions and Fees

There are several types of transactions on the Minter network:

TypeSend                = 0x01
TypeSellCoin = 0x02
TypeSellAllCoin = 0x03
TypeBuyCoin = 0x04
TypeCreateCoin = 0x05
TypeDeclareCandidacy = 0x06
TypeDelegate = 0x07
TypeUnbond = 0x08
TypeRedeemCheck = 0x09
TypeSetCandidateOnline = 0x0A
TypeSetCandidateOffline = 0x0B
TypeCreateMultisig = 0x0C
TypeMultisend = 0x0D
TypeEditCandidate = 0x0E

Each comes at its own fee. A distinctive feature of Minter is that transaction fees can be paid in any coin, even in the one created by the user. This is possible due to the fact that on Minter, each coin has a market value, and it is possible to instantly convert a custom coin into a base one.

The overall transaction structure is as follows:

Transaction {
Nonce
ChainID
GasPrice
GasCoin
Type
Data
Payload
ServiceData
SignatureType
SignatureData
}

Let us now review each transaction type separately.

Send allows users to send coins to anyone via the blockchain. The cost is 0.01 BIP.

SendData {
Coin // Coin to send
To // Receiving address
Value // Amount to transact
}

With SellCoin/BuyCoin, one can sell or buy a particular number of coins. Since the price of a coin on the blockchain is constantly changing, it is difficult to predict what it will be at the time of execution of the transaction. Therefore, we had to split these two transactions. In one case, the user wants to buy a fixed number of coins, and in the other, sell a set number of coins. The cost of coin conversion transactions is 0.1 BIP.

SellAllCoin allows one to sell all the coins of a given type. This is convenient when one wants to get rid of all the coins in their wallet while also paying the conversion commission with them.

In SellCoin/BuyCoin/SellAllCoin transactions, the sender must also indicate the maximum number of coins they want to spend or the minimum number of coins they wish to get. This way, malicious users or even validators cannot use the coin purchase transaction to enrich themselves at the original sender’s expense.

BuyCoinData {
CoinToBuy // Coin for purchase
ValueToBuy // Number of coins to buy
CoinToSell // Coin for sale
MaximumValueToSell // Maximum number of coins to sell
}
SellAllCoinData {
CoinToSell // Coin for sale
CoinToBuy // Coin for purchase
MinimumValueToBuy // Minimum number of coins to buy
}
SellCoinData {
CoinToSell // Coin for sale
ValueToSell // Number of coins to sell
CoinToBuy // Coin for purchase
MinimumValueToBuy // Minimum number of coins to buy
}

With CreateCoin, one can create their own coin in a single transaction.

CreateCoinData {
Name // Name of the coin
Symbol // Ticker symbol of the coin
InitialAmount // Initial supply
InitialReserve // Initial reserve
ConstantReserveRatio // CRR of the coin
}

DeclareCandidacy allows one to “declare” the validator on the network and start validating the blockchain. The transaction cost is 10 BIP.

DeclareCandidacyData {
Address // Address for managing the validator and receiving the coins
PubKey // Validator’s public key
Commission // The fee to be charged from delegators
Coin // The coin to be staked
Stake // Number of coins
}

Delegate and Unbond allow one to delegate funds to or unbond them from a masternode. The cost of each is 0.2 BIP.

DelegateData {
PubKey // Validator’s public key
Coin // Ticker symbol of the coin
Value // Number of coins
}
UnbondData {
PubKey // Validator’s public key
Coin // Ticker symbol of the coin
Value // Number of coins
}

RedeemCheck is used to claim a check. The transaction cost is 0.03 BIP. The peculiarity of such transactions is that the commission payment will be deducted from the balance of the creator of the check, and not from the sender of the transaction. This allows users to redeem checks on new accounts. Funds from the check will be credited to the address of the transaction sender.

RedeemCheckData {
RawCheck // Check
Proof // A proof signed by the recipient
}

SetCandidateOnline/SetCandidateOffline are used to enable or disable the masternode. This transaction costs 0.1 BIP.

SetCandidateOnData {
PubKey // Validator’s public key
}
SetCandidateOffData {
PubKey // Validator’s public key
}

CreateMultisig allows one to create an account that will be controlled by several private keys. The transaction cost is 0.1 BIP.

CreateMultisigData {
Threshold // The threshold for sending a tx from the address
Weights // List of “weights”
Addresses // Address list
}

With Multisend, one can send coins to multiple recipients at once. For the first address, a fee of 0.01 BIP is charged, and for the next, 0.005 BIP.

MultisendData {
List // SendData list
}

EditCandidate allows one to change the validator data: the address for managing the validator and the address for receiving block rewards.

EditCandidateData {
PubKey // Validator’s public key
RewardAddress // Address for rewards
OwnerAddress // Address for managing the validator
}

Also, in each transaction, you can send up to 1,024 bytes of useful data. On each byte, a commission of 0.002 BIP is levied.

Checks

To attract a user base, many projects will need to distribute their coins to users who may not even have an account with Minter. Specifically for cases like that, we developed the check system.

Example of the check:

Mcf89b01830f423f8a4d4e5400000000000000843b9aca00b8419b3beac2c6ad88a8bd54d24912754bb820e58345731cb1b9bc0885ee74f9e50a58a80aa990a29c98b05541b266af99d3825bb1e5ed4e540c6e2f7c9b40af9ecc011ca0387fd67ec41be0f1cf92c7d0181368b4c67ab07df2d2384192520d74ff77ace6a04ba0e7ad7b34c64223fe59584bc464d53fcdc7091faaee5df0451254062cfb37

Minter Check is a signed message that says, “I permit the bearer of this check and password to receive a specific number of coins from my address.”

The check contains the following information:

Each check is password-protected so that they cannot be intercepted and redeemed by the wrong address. The proof is generated along with the password, which allows for the check to be claimed by its rightful recipient.

Issuing a check in Minter Console

Consensus: Validators and Delegators

We approached the development of validator and delegator logics carefully as we wanted every user to take part in maintaining the network and get a reward for it.

So we came up with the following scheme:

A problem surfaced, however, with the delegation of custom coins. Suppose there is coin A. The sale of 100 units brings 10 BIP, but the sale of 200 units would bring only 15 BIP. This occurs due to the floating price of each coin sold. Imagine this:

The real value of 200 coins is 15 BIP. But the stakes are counted separately, so the real number of delegated coins is 100 coins + 100 coins = 20 BIP. It turns out that this way, one can deceive the system and delegate more coins than they actually have.

To resolve this issue, we had to introduce the following mechanism:

But one of the coolest validation solutions is that for each block, we reward ALL active validators proportionally to their stake. Delegators and validators do not need to wait until their node has mined a new unit to receive a reward as it happens on traditional networks. Therefore, on the Minter blockchain, all validators and delegators receive their rewards every 5 seconds, and they are credited to the account once in 12 blocks (1 minute).

To protect against long-range attacks, we freeze the funds delegated to the node for 30 days after their “unbonding.”

Penalties for Validators and Delegators

Reliable work of validators is crucial for the blockchain. First, the more stable the validators work, the greater the network throughput. Secondly, the Tendermint consensus allows for the generation of blocks only if 2/3 of the network capacity is on-line. It turns out that if for some reason, 1/3 of the network capacity goes off-line, the blockchain stops. To avoid this, we designed a system of economic incentives for validators.

Validators can be fined in two cases:

Development of Wallets, Applications, and Blockchain API

Our primary goal was to make the blockchain as easy-to-understand as possible. Therefore, even before the launch, we decided to develop all the services and wallets necessary for users. Thus began the development of wallets for Web, Telegram, iOS, Android, as well as for services such as Explorer, Status, and Gate.

We decided to make the node API as simple as possible so as not to overload it with unnecessary work. Therefore, it contains only basic methods — i.e., viewing blocks, transactions, and user balances. No sorting or searching. Data aggregation and analysis will be carried out by other services.

All wallets had to follow uniform standards, so we came to the following solution:

To enable users to sign in to their wallets by username and password, we developed a mechanism for storing private keys on the server. The private key of the wallet is encrypted with a password set by the user. After that, in an encrypted form, it is sent to the server and saved there. When the user wants to enter their wallet, they receive an encrypted copy of the private key from the server and decrypt it with their password.

Thus, even if the database is completely compromised, attackers will not be able to gain access to users’ private keys and their funds.

Below are the links to the wallets that we eventually developed:

BIP iOS Wallet Testnet

BIP Android Wallet Testnet

BIP Telegram Bot Wallet Testnet

BIP Web Wallet Testnet

Console

Minter Console

https://testnet.console.minter.network

This is one of the most critical web services through which users can interact with the Minter blockchain.

The console operates in two modes:

The primary function is making all types of transactions: sending, converting, and creating coins, declaring and editing the masternode, delegating and unbonding the coins, as well as issuing and redeeming the checks. Also here you can see your balance and recent transactions.

Development of Services: Explorer, Status, and Masternodes Monitoring

https://testnet.explorer.minter.network

Aiming to let users observe processes occurring on the blockchain, we developed several services.

Explorer is the most important of them. The main goal of a blockchain explorer is to collect network data so that one could further analyze it and retrieve it in a human-understandable format, with an ability to search, filter, and view network identities such as blocks, transactions, and validators.

Just like most blockchain networks, we also needed one. Not always this data can be obtained from a node. Moreover, it is not what nodes are intended for, and too many tasks can lead to network congestion. We decided to develop Minter Explorer, but soon the project’s requirements increased, and the explorer has evolved into a gateway for the communication between the blockchain network and our applications.

For more detail, please refer to the article entitled A Chronicle of Minter Explorer Development.

Minter Testnet Explorer

Achieving the Maximum Transaction Processing Speed

Floating tx fee

To protect the network from spam, we introduced the floating transaction fee system. The cost depends on the number of transactions in the mempool (list of unconfirmed transactions) of nodes. Now it looks like this:

if mempoolSize > 5000 {
return 50
}

if mempoolSize > 1000 {
return 10
}

if mempoolSize > 500 {
return 5
}

if mempoolSize > 100 {
return 2
}

return 1

To put it in plain English: if there are over 100 transactions in the mempool, the fee increases two-fold. If more than 500, five-fold.

Even at the highest transaction fee possible, the cost of sending the coins to the account would be as low as $.01.

Floating network power

In the process of development, we encountered the problem of centralization. If there is a validator node capable of conducting many more transactions than all the others, then it will gradually crowd out competitors and in the end, remain alone on the whole blockchain. To avoid this, we introduced the system of “floating power.”

This system limits the maximum number of transactions in a block, depending on how long it took the previous block to be generated. If the actual block time differs substantially from the estimated one, then the possible number of transactions starts to decrease (by 30% per block) until the majority of validators can process them at the required speed. Once the network has recovered, the maximum number of transactions starts to rise 5% per block.

Crash Recovery Mechanism

We spent a lot of time developing and testing our blockchain. Tens of testnets were launched, tens of millions of transactions were processed, and an open bug bounty program was launched. Still, many modules of our blockchain are new in the market, and we do not exclude the possibility that some problems may appear.

There are four main reasons why Minter Mainnet may stop generating blocks. Next, we will examine each of these causes and the ways of restoring the network in case of such failures.

1. A one-time shutdown of ⅓+ of the voting power of the validators

It was a typical scenario for a testnet, which was used to stop the old version of the network and start a new one. The Tendermint consensus algorithm is designed to stop its work if ⅔+ of the voting power did not vote for the block. Such a stop is not considered an error.

Solution: validators should get their nodes back online as soon as possible. If for any reason this is not possible, then a manual fork of the code and update of the remaining nodes will be needed.

2. Protection mode triggering

The Minter node has a built-in data verification mechanism that is activated every 720 blocks. It checks factors such as the number of coins issued, the number of validators, and the number of candidates for validity. If suddenly there is a discrepancy between the real values and the target values, then the node stops with an error.

Solution: the bug that led to incorrect data on the network should be eliminated, and validators need to implement the upgrade and restart their nodes.

3. Error in the code

The error may occur both in the code, for which the Minter team is responsible, and in third-party libraries. The most critical are errors in the Tendermint engine, which can lead to a complete stop of the network.

Solution: the bug that caused the node to stop must be fixed, and validators need to implement the upgrade and restart their nodes.

4. Failure to update ⅔+ of the voting power of the validators

If an upgrade (fork) was released and accepted by more than ⅓ but less than ⅔ of the voting power, then a situation similar to the first point will occur (one-time shutdown of ⅓+ of the voting power of the validators).

Solution: validators need to update their nodes as soon as possible. If for any reason this is not possible, then a manual fork of the code and update of the remaining nodes will be needed.

A critical situation and the impossibility of a hard fork

We have prepared a specific tool for cases where the further operation of the network is impossible. In critical situations, data from the blockchain can be downloaded, and a new network can be launched on its basis.

Data to be downloaded:

Transactions, blocks, and other data will be available on the previous network. The new network will begin its life from the first block.

Supporting development and adoption of Minter, a digital assets marketplace powered by a fast blockchain. Other social media: minter.org/#follow