Outputs / How To Optimize Your Wallet?

Your balance is made up of outputs of various amounts which you've received in the past. Every time you send, some of those get combined together until you reach some amount, which is then sent to the destination, and some change returned to your wallet.

Think of outputs as bills: you received a bill of 40 and 100 in the past, and now you want to pay something worth 120. Your wallet “burns” the 100+40 bills, create new bills of 120 and 20, sends the 120 to your recipient and returns the 20 to yourself and you're left with the bill of 20, plus whatever else you already had in the wallet. Cryptonote protocol then combines multiple outputs in a ring-signature, effectively hiding the one actually getting spent among other outputs found in the ring signature and needs to choose other outputs of the exact same value. This required splitting any amount into multiple outputs with common denominations, but there were always some of them which were unique, like 0.000006839355. There's simply no other like it, so there are no other outputs among which it could hide, and it would have to get spent alone. It's a special case which doesn't benefit from applying ring signatures and thus the special treatment. Because of this, you'd only want to use it once to join it with other outputs. The “optimize” command is there to get rid of those special outputs once and for all (if you actually have them in your wallet, that is).

Depending on how much CCX you want to transfer, you might run into the error “Transaction size is too big, please optimize your wallet” or “Transaction is too big”. Often, this is because of a lot of small incoming transactions.

With the CLI wallet or the GUI wallet, you can optimize your wallet to send larger transactions or a single big transaction. Like any other transaction on the network, you will need to wait for confirmation of the optimization transactions to spend those funds.

The process of optimizing your wallet takes all your small incoming transactions and combines them into bigger ones by sending them to yourself. It is akin to replacing a handful of small currency bills with a single larger one. Once the process is complete you will be able to send larger transactions. You need to wait for a period of 11 blocks which amounts to 11 * 2 = 22 minutes more or less. Your funds will be locked during this time.

Important: Wallets used by service providers like Exchanges should schedule regular optimizations and run optimizations consecutively until outputs are less than 100.

CLI Optimization

In the CLI wallet there are three commands that help you optimize your wallet:

outputs

This command shows you the total number of outputs in your wallet. The more outputs in your wallet, the more optimization your wallet will need to send large transactions. If you have less than 100 outputs, then you do not need to optimize your wallet.

[wallet ccx7Pz]: outputs
233

optimize

When you run this command, it runs a single optimization round, usually reducing the number of outputs by a 100. You can do this over and over again until you can the desired amount.

[wallet ccx7Pz]: optimize
Money successfully sent, transaction
c273bb88f7957c3bc25f79ff2494a30ffa226d3a06c95f3ba49eb4b6dc334e97
Transaction secret key
02464c66f23f077e9bd859e5aec87d2b8802f4f6871e860ee212398e8782cf0d

Then you will see that the number of outputs has reduced:

[wallet ccx7Pz]: outputs
136

optimize_all

When you have thousands of outputs or want to send one large transaction, that involves all or almost all of the funds in your wallet, then you can run this command. The command runs several optimization rounds at once. You will see the number of outputs and the number of optimization rounds that the process will run. Some wallets, with several thousand outputs, will need several rounds of optimize_all. It depends on how much you want to send and how many outputs you have.

[wallet ccx7Pz]: optimize_all
Total outputs: 396
Total optimization rounds: 3

Important: Always use the latest version of concealwallet

GUI Optimization

In the GUI wallet, the command to optimize the wallet is found under Settings → Optimize Wallet

The value you see in the window is the total number of outputs in your wallet. The more outputs in your wallet, the more optimization your wallet will need to send large transactions. If you have less than 100 outputs, then you do not need to optimize your wallet.

When you run this command, it runs several optimization rounds for your entire wallet. You can do this over and over again when you have thousands of outputs or want to send one large transaction, that involves all or almost all of the funds in your wallet.

Important: The optimization transactions require confirmation like normal transactions, and as such, the funds will not be available until after the confirmation period.

Fusion Transactions

A common issue for any service provider is the “Transaction is too big” error when trying to execute a transaction. The Cryptonote protocol uses denominations when sending funds and as a result after a lot of incoming transactions, that wallet address can up with hundreds, or even thousands of small outputs.

The solution, for anyone that uses our RPC Wallet is to use fusion transactions to consolidate all the smallest outputs, so that users can send larger amounts. The more outputs you have, the more fusion transactions you will need to do. Fusion transactions use a threshold value to determine how many outputs to fuse. Always use atomic units for the threshold value. For example, if you want to fuse all inputs smaller than 1 CCX, then the threshold will need to be 1000000.

Fusion transaction follows a two-part process:

  1. First use the estimateFusion RPC call to determine the best threshold to optimize.
  2. Then use sendFusionTransaction to fuse those outputs.

Step 1 - estimateFusion

In the examples below, we will look at using estimateFusion to see how many inputs we can fuse for a specific address in the wallet. If the wallet contains only one address, you can omit this parameter.

Example 1: with a single Wallet address:

{
   "params":{
      "addresses":[
         "ccx7FWKwU67Juvyw5JNmyCEWnEQLCJs196hpHYCbSCWGGykBFZnUnhfLhJUWwU1ixvVTadF5pdGteTMpZyKs5A1D1Lrv8ttyY3"
      ],
      "threshold":1000000
   },
   "jsonrpc":"2.0",
   "id":"test",
   "method":"estimateFusion"
}

The output:

{
   "id":"test",
   "jsonrpc":"2.0",
   "result":{
      "fusionReadyCount":298,
      "totalOutputCount":301
   }
}

Example 2: with another wallet address from the same container:

{
   "params":{
      "addresses":[
         "ccx7MxD8iGAgbvsQojKgZWCz1hzhAZ6RWcjoKgF3Cc9zCzG7xmP1fvRLhJUWwU1ixvVTadF5pdGteTMpZyKs5A1D1Lrv8afeB3"
      ],
      "threshold":1000000
   },
   "jsonrpc":"2.0",
   "id":"test",
   "method":"estimateFusion"
}

The output:

{
   "id":"test",
   "jsonrpc":"2.0",
   "result":{
      "fusionReadyCount":0,
      "totalOutputCount":63
   }
}

Example 3: without specifying the address (this will show the total outputs for all wallets in the container:

{
   "params":{
      "threshold":1000000
   },
   "jsonrpc":"2.0",
   "id":"test",
   "method":"estimateFusion"
}

The output:

{
   "id":"test",
   "jsonrpc":"2.0",
   "result":{
      "fusionReadyCount":343,
      "totalOutputCount":364
   }
}

Note: Please remember that you need to specify the addresses param as an array of strings or you will get the outputs for all the addresses in your container.

Step 2 - sendFusionTransaction

Now that we have determined that we can use fusion transactions to optimize the wallet, we can go ahead and use sendFusionTransaction with the same above threshold. Once again, if the wallet only contains one address, you can omit the use of the address in the parameters.

Example: with Wallet address:

{
   "params":{
      "addresses":[
         "ccx7FWKwU67Juvyw5JNmyCEWnEQLCJs196hpHYCbSCWGGykBFZnUnhfLhJUWwU1ixvVTadF5pdGteTMpZyKs5A1D1Lrv8ttyY3"
      ],
      "threshold":1000000,
      "anonymity":0
   },
   "jsonrpc":"2.0",
   "id":"test",
   "method":"sendFusionTransaction"
}

The output:

{
   "id":"test",
   "jsonrpc":"2.0",
   "result":{
      "transactionHash":"ea749cd4cf407f5082ec2a20dc71692b470ad2fdf706aaa851ed3926d890c579"
   }
}

Note: If you use sendFusionTransaction on an address that does not have sufficient fuseable inputs, you will get an “index out of range” error.

Q: What happens if we have thousands of outputs?

When dealing with a wallet where the number of smaller outputs have built up over time, then you will need to use smaller and smaller values for the threshold. In some cases, use a threshold of 10 or lower to fuse the smallest values. In the rare scenario where there are too many small outputs even at the lowest threshold, you will need to export the keys for that wallet and use the CLI or GUI wallets to run multiple optimization rounds.