Well, when a coinbase transaction and a fusion transaction love each other very much…
Just kidding. Grab a drink, this is a long, and confusing read.
Lets start by looking at where the money for a transaction comes from in the first place. All money originates in the network from mining – which creates new coins, via a coinbase transaction.
A coinbase transaction is a special kind of transaction that is rewarded to the person who mines a block. The money ‘magically’ appears, and is not sent to the miner by anyone.
This might make you think that miners can print as much money as they want. However, the coinbase transaction cannot be more than the current ‘reward’ – if it is, the other pools and daemons will reject the block containing it. The current reward is calculated by looking at the emission curve, and the total amount of coins in the network.
Lets say Bob decides to do some solo mining, and gets lucky one day. Maybe he mined block 900,000.
Bob got 29,013.99 TRTL from mining this block. As you can see, this transaction has no inputs, because it is a coinbase transaction. The bit we’re interested in here are the outputs. Interestingly, Bob does not just receive a big chunk of 29,013.99 TRTL. Instead, he receives 6 outputs, of varying amounts, which add up to the full 29,013.99 TRTL.
Whenever a transaction is sent, it must be split into denominations. This is quite simple to do – it’s just splitting into units, such as thousands, hundreds, tens, etc.
The reason for this is due to how the mixin / privacy features work. When we form a transaction, we need to match the amounts we use with other ones other people have sent. If we didn’t split our outputs into these standardized amounts, we would need other people to have made transactions of exactly 29,013.99 TRTL before, which is pretty unlikely. Think of these standard amounts as building blocks to make any transaction amount.
So, Bob has got an amount of TRTL now, comprised of a few separate outputs. How does he spend them?
Finding which transaction outputs belong to us
First, Bob needs to work out if this transaction belongs to him. Since CryptoNote coins are private, we can’t tell what address a transaction was sent to without owning the private keys belonging to that address.
Now we’re going to have to get a bit nerdy and talk through some code. I’ll try and keep it simple. If you want to follow the code, check it out here.
Each transaction has a transaction public key which comes with it. We start by taking this public key, and our private view key, and performing some magic crypto operations, we can generate a key derivation.
Next, we loop through each output in the transaction, so in this case we’d start with the 0.09 TRTL output.
For each output in the transaction, we take our key derivation, the output index (This is simply the ordering of the outputs in the transaction), and the output key (That’s the long hex string which looks like a hash in the image)
We do some more magic crypto operations, and we get out a public spend key. This is the public spend key that the transaction was sent to.
If you weren’t aware, a TurtleCoin address (and any CryptoNote address, actually) is just a ‘nicer’ representation of the public spend key and the public view key.
For example, the address:
corresponds to the public spend key:
and the public view key:
So, we’ve got out the public spend key this transaction was sent to. What’s next? We just need to checkout if that public spend key is the same as the public spend key our wallet uses.
If it is the same as the public spend key our wallet uses, this transaction output belongs to us!
By the way – if the transaction doesn’t belong to us, we won’t get out the actual spend key the transaction was sent to – we’ll just get some meaningless garbage. So, your privacy is intact 😉
We then repeat this process for every output in the transaction. We can’t automatically assume because one output belongs to us, they all do. Remember, you can send a transaction to more than one person at once.
Once we’ve added up the outputs that belong to us, we’ve worked out how much we’ve been sent in this transaction. In Bob’s case, that’s 29,013.99 TRTL. Good work, Bob!
Storing the magic stuff which lets us send transactions
Bob’s got his wallet all synced. He wants to buy a TurtleCoin t-shirt from Alice. How does he send his money?
If we find that a transaction output belongs to us, we can then create a transaction input from that, using our private spend key. We can then spend those inputs, creating new outputs, for someone else to repeat the cycle with. A little bit confusing.
There are a few bits of information we need to store that comprise our new input. We need:
- The transaction public key – This is included in the transaction.
- The output index – This is the output index previously mentioned.
- The amount – We can take this from the output data.
- The key – This is the output key we used before.
We also need the global output index. This is part of the output data. This is used to keep track of all the output keys. Each different amount has a different global output index store. So, the first ‘1’ amount that was ever used in a transaction gets a global output index of 0. The second ‘1’ amount gets an index of 1, and so on. If someone then sends a ‘2’ amount, this gets an index of 0, since the indexes for different amounts are not related.
That’s a bit confusing, but if you don’t understand it, don’t worry – It doesn’t really matter.
Finally, we need to generate this inputs key image. To do this, we need to take the key derivation from before (remember that?), and our private spend key. We then perform yet again some magic crypto operations, and we are left with the key image.
Because we need to generate a key image to spend our funds, and we need a private spend key to do so, this allows us to create ‘view only’ wallets, which can only find incoming transactions, and cannot spend them, since it has no private spend key.
If you’re feeling utterly baffled by the previous explanation, the following diagram might help. Or, it might confuse you more. Sorry!
Spending our transaction inputs
Bob has got his transaction inputs all ready in his wallet. Surely he’s able to make a transaction by now?? Good news Bob. Let me explain the steps he needs to take.
Selecting the inputs
Link to the code here.
To start with, we need to find enough inputs to cover the amount Bob wants to send. Alice is sending her t-shirts for 25,000 TRTL, so we need at least that much. He also needs at least 0.1 TRTL for the network fee.
Inputs are selected randomly, to make it harder to detect any patterns in spending. We just keep taking inputs whilst we don’t have enough funds to cover the transaction.
Lets say that the inputs that get randomly selected are 3 TRTL, 0.09 TRTL, 20,000 TRTL, and 9000 TRTL. That sums up to 29003.09 TRTL, so we’ve got enough to cover the transaction.
Since Bob only wants to send Alice 25,000 TRTL, but he doesn’t have the exact amount to send, he instead sends the ‘change’ back to himself. In this case he wants to send 25000 TRTL + 0.1 TRTL (for the network fee) and he’s got 29003.09 TRTL in the inputs, so he needs to send 4002.99 TRTL back to himself.
Preparing the destinations
Link to the code here.
Now we need to split this 29,003.09 into separate atomic amounts, and indicate who we’re actually sending each bit to.
Alice has given Bob her address, which we extract the public spend and view key from. We then split the 25,000 TRTL we’re sending her up into units, which is simply 20,000 TRTL + 5000 TRTL. These will eventually become two outputs for Alice to scan, just like we did at the beginning of this article.
Next, we need to setup the destinations that Bob is sending to himself. We take our address, split it into a public spend and view key, and again split up the amount into units. This will give us 4,000 TRTL + 2 TRTL + 0.9 TRTL + 0.09 TRTL.
So, the transaction will have 6 outputs – 2 belonging to Alice, and 4 belonging to Bob.
Outputs = 20000 TRTL + 5000 TRTL + 4000 TRTL + 2 TRTL + 0.9 TRTL + 0.09 TRTL
Preparing the Transaction Inputs
Link to the code here.
Next we need to hide our real inputs among other inputs, to obscure which inputs are really used to create the transaction. We ask the daemon for as many fake outputs as our mixin value, and we need this many for each amount we are sending. If we are using a mixin of 3, we need 3 fake outputs for 20,000 TRTL, 3 for 9,000 TRTL, and so on.
Next, we loop through each real input, and the fake outputs. We generate a key image using the real input transaction public key, our private view key, and our private spend key. This also gives us a temporary key pair for each transaction input, which we’ll need later for our ring signatures.
Now we can finally make a transaction input, which consists of the amount, the key image we just generated, and the global output indexes of both the fake outputs and our real input. Gah, confusing.
We end up with 6 transaction inputs, with each one having 3 fake global output indexes, and one real global output index. No-one but us can tell which is the real index.
Preparing the Outputs
Link to the code here.
Now we can make the outputs of the transaction. We start by generating a random key pair. This is used so multiple transactions to the same address cannot be linked together.
Next, we loop through the destinations we prepared earlier. We generate the output key by taking the receivers public view key, the private key from the random key pair we just generated, and the receivers public spend key.
Then, we create our output, which is just comprised of the output key we just generated, and the amount the output is worth.
We store the public key from the random key pair we generated – this becomes the transaction public key later.
Assembling the transaction
Link to the code here.
We’ve done most of the work now, we can start putting this transaction together. We start by creating the tx_extra – This has a few bits of data in, but most importantly is the transaction public key. If we’re using a payment ID, we also add that in here.
Then, we copy over the inputs and outputs we prepared earlier, and add a few extra bits like the transaction version, and the unlock time if you want your transaction to not be spendable instantly.
Finally, we hash this data to give us the transaction prefix hash.
Generating the Ring Signatures
Link to the code here.
Finally, we generate the transaction ring signatures. These are used to verify that we own all the funds being spent. We generate signatures for each transaction input, using the private key of the temporary key pair we created for each input earlier, the transaction prefix hash, the public key that each fake transaction output has (including our real input), and each transaction input key image. This again, uses some cryptography magic.
Ring signatures indicate that one person of a group signed a message with their private key, but it cannot be determined which person signed the message. This proves we are able to spend the amounts in the transaction, but our identity is kept hidden.
Sending the transaction
Finally, we’re done! We send our transaction off to a daemon, and if it verifies the transaction is legitimate, Alice will get her funds shortly. There’s one thing we missed when I explained this – detecting when you have spent funds, rather than just when you have received funds.
Finding which transaction inputs belong to us
Fortunately, this bit is pretty simple. Remember when we generated a key image, when we found a transaction that belonged to us? Because that key image is used in a transaction when we send it, we simply look at each transaction input, and if it uses a key image which we created, then we sent it.
Thus, when Bob scans the transaction he sent to Alice, he will see the 4 inputs we used to create the transaction, and find that they use key images he previously created. He will mark these key images as spent, so he doesn’t accidentaly use them in another transaction. This would cause an attempted double spend, which would fail, as a key image can only ever be used once.
When Bob sums the transaction inputs, he would get 3 TRTL, 0.09 TRTL, 20,000 TRTL, and 9000 TRTL – The exact amount he sent. He should then scan the transaction outputs, and find 4 outputs that belong to him – 4000 TRTL + 2 TRTL + 0.9 TRTL + 0.09 TRTL – The change that he sent back to himself.
With this, Bob can work out the total amount he spent on the transaction – inputs – outputs = 25000.1 TRTL.
You may remember that Bob decided to pay a network fee of 0.1 TRTL, but we never gave an address to send this to. The network fee is simply the difference between the sum of the inputs, and the sum of the outputs – the miner who includes this transaction in a block is allowed to add this amount to the coinbase transaction as a reward.
In summary, a transaction is comprised of inputs, outputs, and ring signatures.
- Transaction inputs are money we have previously received, combined with some data to generate the keys. They are also hidden among other people’s inputs.
- Transaction outputs are money that the receiver(s) get. This may include some change which returns to the sender.
- Ring signatures prove the transaction is valid and we own the corresponding private keys. This is an example of a zero knowledge proof: A third party can prove the signatures are legitimate, but it gives them no information about who the sender is, or who the receiver is, just that the transaction is legitimate.
- If a transaction input has the same key image as one we generated, that is an outgoing transaction by us.
- If a transaction output has the same public spend key as ours when decrypted, that is an incoming transaction for us.
I’m sorry if you didn’t understand this. It’s quite confusing, and quite hard to explain. I have to say, the whole inputs, outputs, fake outputs + real input thing confuses me as well.
Thanks for reading – hopefully you learnt something!