How to Implement 5% APR

This is one of the characteristics of BTCD so part of KMD requirements. BTCD used the peercoin utxo staking method. What that means is it added a required timestamp field to transactions and staking required spending an old utxo and creating a new one (usually two). So this leads to every increasing amount of work that is needed to do and also adds a lot of transactions to the blockchain.

With KMD’s underlying block generation being equihash PoW, to add a utxo staking would require essentially recreating the peercoin PoS changes.

Nothing against the peercoin method, but for KMD with the notary nodes generating blocks using a modified zcash round-robin PoW, I wanted a more efficient way to deal with the 5% APR. I saw how siacoin awarded siafund interest when you spent it, which seemed a much more efficient method as it didnt take any blockchain space, nor did it need any continuously increasing amount of calculations.

of course, making such a change to the zcash codebase is easier said than done. All places that need to know how much is being spent needs to be adjusted to account for the accrued interest. Finding all such places wasnt easy and still not sure I found them all, but I got the basics working with the latest version.

To avoid creating a fork, it is just displaying the accrued interest now. Once all the various places are showing the identical values, then I can enable actually creating the coins to match the accrued interest. Since the txfee is calculated as (Sum(inputs) – Sum(outputs)), by increasing the effective amount of the inputs it would increase the txfee. So, in addition to boosting the input sum, all the places that creates transactions needs to be adjusted. That way, the amount paid for txfee will match what the sender wanted to and the value of the interest obtained.

To avoid awarding interest on dustlike outputs, I set the threshold to 1.0 KMD to be eligible for getting interest. Interest is paid by each minute, using the nLockTime of the transaction against the nTime of the previous block. No need to worry about people iterating sends to themselves each block as the txfee will eat up most of the interest if the timeframe is small.

People familar with bitcoin protocol will exclaim “most transactions dont have nLockTime set! and even if they did, there is no assurance it wasnt set arbitrarily in the past”

At least, that is what I thought at first. Then I realized that I could add a constraint that if nLockTime is set to be a timestamp, then it needs to be within some reasonable gap from the current time. current time as defined by the chaintip’s nTime so we can get consensus on all interest calculation durations. By using nLockTime, it makes it a field that is somewhat useful and instead of being almost always 0, it will be a useful timestamp for all tx.

If anybody sees any issues with actually using nLockTime as a transaction timestamp, let me know. If it is used as a block height, then it wont earn interest, but that is a special case usage. For transactions that use the nLockTime actively, like the DEX protocol, the locktime is set to a near future value, which will still start the interest accruing from that point in time.

I changed the wallet to add a timestamp that is based on the chaintip’s nTime so by sending funds to yourself you can create a transaction that will start earning interest. then using listunspent or other RPC, you can see the accrued interest. its cool how it keeps increasing each minute, even though it is just satoshis.

from listunspent:

{
"txid" : "bf0876b211c1abc3b1f9f5c1a129d81e2b6b070c112ddffe7971ab82d3b309fe",
"vout" : 0,
"address" : "RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc",
"account" : "",
"scriptPubKey" : "76a9148ee61a3161993f4f7b7081259bf5f3322d65d3f888ac",
"amount" : 1.00000000,
"interest" : 0.00011876,
"confirmations" : 1225,
"spendable" : true
},

from getrawtransaction:

"vout" : [
{
"value" : 1.00000000,
"interest" : 0.00011904,
"n" : 0,
"scriptPubKey" : {
"asm" : "OP_DUP OP_HASH160 8ee61a3161993f4f7b7081259bf5f3322d65d3f8 OP_EQUALVERIFY OP_CHECKSIG",
"hex" : "76a9148ee61a3161993f4f7b7081259bf5f3322d65d3f888ac",
"reqSigs" : 1,
"type" : "pubkeyhash",
"addresses" : [
"RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc"
]
}
},
"confirmations" : 1228,

from gettxout:

{
"bestblock" : "012d0a5510ac52d8bd0eacf81cd6dd2d6907233e0b0fb0c983d90cebf475cf8c",
"confirmations" : 1293,
"value" : 1.00000000,
"interest" : 0.00012224,
"scriptPubKey" : {
"asm" : "OP_DUP OP_HASH160 8ee61a3161993f4f7b7081259bf5f3322d65d3f8 OP_EQUALVERIFY OP_CHECKSIG",
"hex" : "76a9148ee61a3161993f4f7b7081259bf5f3322d65d3f888ac",
"reqSigs" : 1,
"type" : "pubkeyhash",
"addresses" : [
"RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc"
]
},
"version" : 1,
"coinbase" : false
}

I could have gotten this implemented in iguana in just a few hours, but I am still in the process of getting familiarized with the bitcoind C++ code, so that explains why it took me so long to add accrued interest and still it isnt in all places that are needed. When we can verify that the interest is being displayed properly in all places, we can deploy a hardfork that actually awards it. Not sure when that will be, the last hardfork created a fair amount of confusion, so I want to minimize the number of these we do, even if it is just for “testnet”

So, it seems I am ahead of schedule and I hope people wont mind if I take the rest of the weekend off.


Bitcointalk Topic Entry

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *

3 + 11 =