An Optimization Tool for Cryptonote Based RPC Wallets
Cryptonote derived codes, such as Niobio Cash, use the concept of transaction inputs and transaction outputs to create a transfer of coins from one wallet to another. This often leads to a problem where the transaction being built becomes too large and is rejected by the code. The common workaround is to break the transfer into smaller ones. There is a special kind of transaction, called fusion transaction, that can be used to optimize these entries and prevent the problem. We’ll dig on the details below.
Transaction inputs, or simply tx inputs, can be seem as the money bills someone have on his pocket. Let’s take Carol as example. At some point in time other person or persons give Carol this money and she now keeps them on her pocket. These money bills are the so called tx inputs which, summed up, represent the total amount available she has to spend at this moment. If Carol wants to pay someone a certain amount of money, she must select a group of money bills that compose a value equal or bigger than that required amount, and she must be able to hold them all on her hands.
On Cryptonote’s blockchains, a similar process is used. A transfer between wallets is made by a transaction, which in turn contains a group of tx inputs that represents part (or total) of the funds of the sender, and the tx output locking that amount to the receiver of the payment. The tx output of a transaction will become the tx input for a future transaction, when the receiver of the former transfer will act as a sender.
The Problem #1
Now imagine a situation where Carol holds a lot of one cent coins and needs to pay two thousand dollars to a friend. She has the amount, but her hands won’t be able to hold all these coins at once. On real world this is a bizarre situation, but for cryptocurrencies on a blockchain it’s a common case. Many wallets receive thousands of small value payments from mining or from faucets, and when their owners need to transfer some amount the transaction becomes too big to be created (don’t fit on their hands).
There is another factor that contributes to an even bigger transaction. We have a system of privacy that mix copies of unrelated tx inputs with the transaction, creating a diversion mechanism to protect the identity of the sender of the coins. Depending on the anonymity factor used, the number of tx inputs used can be ten times the number of the actual inputs, or even more.
The Solution #1
What is being commonly called wallet optimization is a process of changing the small value bills for higher value ones. If Carol can go to the bank and change two thousand dollars, in one cent coins, for twenty bills of a hundred dollars each, she will be able to hold them all together and make the payment she needs to.
This solution is brought to blockchain in the form of the fusion transaction, which differs from the regular transaction on two major points: the sender and the receiver are the same address, and this kind of transaction doesn’t pay fee. In other words, Carol sends two thousand dollars to herself.
The code on her wallet will take many small tx inputs and group them into a single tx output. As she acts as the sender and the recipient on this transaction, this tx output can be used by her as a tx input to pay somewhere else, on a next step.
The RPC wallet API, on most Cryptonote currencies, has an endpoint to create such fusion transactions.
The Problem #2
The RPC Wallet (walletd) is mainly used by exchanges and web wallet providers. A substantial percentage of their support tickets are related to failed withdraws from their customers. And guess what? Most failures are caused by the transaction too big problem.
So why don’t they run fusion transactions?
The answer may differ on details, but they all rely on lack of confidence on this process. It is somehow complex to run this API call on all addresses of the container without writing some kind of script or program to manage it. Walletd is a container of addresses, so first another method must be called to request the list of addresses from the container, then loop them all to call another method on each interaction. A lot of other details must be addressed on this task, such as error handling, time window for running it, among others.
We can only imagine the exchanges don’t want to dig into this matter, mainly because they may not have the technical skills on the specifics of our blockchain code, or maybe they just don’t want to invest time from their technical teams to solve other’s problem.
The Solution #2
The good news is that Niobio Cash developers created a special tool to facilitate the optimization process, bringing safety and a set of options to control the whole activity.
An additional binary tool called optimizer is included on the Niobio Cash node package. It allows an easy way to automate the execution, controlling the maximum duration it is allowed to run, the interval between interactions so the local mempool does not get flooded, and some other handy command line options. It is even possible to run the optimizer on a preview mode, where no actual action is taken, but it can be verified the number of wallets that are eligible to be optimized.
The Tool
The utility is called optimizer and can be found on the package of binaries from the Niobio Cash node daemon. This is the help page for it:
The interval is a pause between each interaction, where an interaction is the creation of a fusion transaction for a wallet on the list.
The duration is the maximum time allowed to the tool remains running. The process is stopped after the limit is reached. This is useful to automate the process, making sure it does not extrapolate a maintenance window.
A few recommendations, although not mandatory:
- The fusion transaction will appear on the customer’s transaction history as a zero amount transaction. To avoid questioning, it may be useful to make a small change on frontend code to hide these transactions;
- It is probably a good idea to create periodic maintenance windows, once a week for example, where the wallets operations are brought offline for customers, and run the optimizer inside these windows. As any other regular transactions, the coins used remain locked until they get into a block, so customer can face a race condition where he will fail to create a transfer attempted on a time frame close to the fusion transaction creation for his account.
Below a image of an execution of the tool, followed by a preview, on a container.
The code for the optimizer tool can be found on github: