A withdrawal limit is exactly what it sounds like, a limit set on addresses dictating the maximum number of coins which can be withdrawn from an address in a certain amount of time. The main downside is that a few extra fields need to be added to the account structure to enable the withdrawal limit system.
The limit is self-set by account owners using a special transaction and the default value for new accounts is unlimited. The purpose of such a system is to help prevent double spending, so that merchants can have more faith in transactions with zero or a small number of confirmations.
How it Works
A brief outline of how withdrawal limits work:
- Send the network a special transaction to modify the withdrawal limit of your account. Limit is specified as number of coins per block, and is saved into queue field. Such change will take effect in eg. 100 blocks and after that time the queued value overwrites the actual withdrawal limit value.
- Network accepts the special transaction and after 100 blocks it will reject any transaction that would cause newly specified limit to be exceeded.
A merchant can ensure he will receive funds by:
- Checking that there is no queued withdrawal limit change on sending account.
- Check that sending account balance is high enough so it can't be emptied too fast.
- Ensure transaction is not low priority and has propagated enough in network.
Withdrawal limits are implemented in Cryptonite and as a result quite secure 0-confirmation transactions are possible. Imagine that a buyer wants to purchase something from a merchant, but neither of them want to wait for confirmations. Before this can happen the buyer must already have an address which has a withdrawal limit set on it. The buyer can achieve this using the following API command:
./cryptonited setlimit "10.0000000000ep" C59FG7kCspznKMhvpLWkAXCDLr4fnmEZxx
Now with this withdrawal limit in place the buyer can only withdraw 10 coins per block at most, so if the buyer has a balance of 500 coins it will take at least 50 blocks to empty the address. The withdrawal limit will be updated immediately in this case because the new withdrawal limit is lower than the last, however the change will be delayed by 100 blocks if the new withdrawal limit is greater than the last.
Now the buyer can send payment to the merchant and once the merchant receives the transaction they can lookup the withdrawal limit and the balance of the address which they received payment from. Since the withdrawal limit and the balance are stored in the account tree this isn't a very computationally expensive task. So to lookup the details of the buyers address the merchant can use the following API command:
./cryptonited listbalances 5 [\"C59FG7kCspznKMhvpLWkAXCDLr4fnmEZxx\"]
This will return details about the buyers address, ignoring transactions with less than 5 confirmations. What the merchant really cares about is the "balance, "limit", and "futurelimit" fields. If the limit field is 10 but the balance is 500 then the merchant knows that the address cannot be emptied quickly. The merchant must rebroadcast the buyers transaction to ensure that it gets into a block quickly enough.
The merchant can also check that there is no pending update to the buyers withdrawal limit by making sure the futurelimit field is the same as the limit field. The futurelimit field is used to delay any increases to the withdrawal limit, so when it holds a value different to the value of the limit field you know there must be a pending update to the withdrawal limit. And there you have it, fast yet secure transactions.
Why it Works
Double spending is possible because you can send one transaction to a merchant while simultaneously sending another one to miners which moves all your coins to another address. But with withdrawal limits you cannot send all your coins at once and this can help secure merchant transactions.
Suppose you have 100 coins in your account with a withdrawal limit of 1 coin per block. To send a secure 0-confirmation transaction of 1 coin you sign a transaction to send 1 coin to the merchant and it's considered valid if included in one of next 10 blocks (or whatever amount is deemed secure).
If an attacker tries to double spend his coins in an alternative blockchain he would only be able to move 1 coin from his account per block, so even if his network branch is accepted as the longest, the merchant transaction will still be valid and included in a later block. To successfully make a double spend the attacker would need to exclude the merchants transaction from the next 10 blocks.
However, if the double-spender issues a very large number of transactions, there's a chance that the legitimate transaction could get excluded from all 10 blocks. There are ways this could potentially be solved, but with the right rules in place there's very little chance an attacker could actually keep a transaction out of the blockchain so long due to the way transactions are prioritized based on age.
However it is important to keep in mind that this withdrawal limit system is not perfect and should not be trusted absolutely by merchants. Cryptonite uses this simple type of withdrawal limit system, so while it can be much safer to accept 0-confirmation transactions in Cryptonite, it's not totally secure and it may be possible to double spend given enough effort on the part of the attacker.