Good day!

I am trying to understand the construct_miner_tx function inside cryptonote_tx_utils.cpp and I am stuck on comparing what is being discussed in the zero to monero reference pdf regarding multiple outputs. Where it generally states (based on what I understand), tx pubkeys are generated in derive_public_keys in crypto.cpp, where one of its parameters is the key derivation. So based on the code, key derivation is called in construct_miner_tx in:

bool r = crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation);

In the paper it states that the PvK and tx sk are multiplied by a cofactor of 8 to ensure that the output point is within G subgroup.

So key derivation is 8*(PvK txsk), right?

Then derive_public_key is H(8*(PvK txsk) || output_i)G + PsK?

PsK = Public spend key
txsk = transaction secret key
PvK = Public view key

Do all my assumptions make sense? And is the output of generate_key_derivation a plain public key? And is the shared secret key the output of hash_to_scalar?

Thank you very much for the clarification.


Let's start by first defining a couple of things. Outputs created in a coinbase transaction can later be spent by using them as inputs to a subsequent transaction. A transaction also has a public key, which is used as the public part of a secret (it's shared, it's in the tx which is on the blockchain).

When constructing a coinbase (miner) transaction, the generated coins are placed as outputs of the transaction. These outputs are only spendable by the miner - they are constructed in such a way that only the miner can spend them (you would need the miners private spend key).

So, in construct_miner_tx:

crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation);

Where miner_address.m_view_public_key is A (the miners public view key) and txkey.sec is r (the tx private key), the output of the function generate_key_derivation (which is placed in derivation), is 8rA.

So key derivation is 8*(PvK txsk), right?



crypto::derive_public_key(derivation, no, miner_address.m_spend_public_key, out_eph_public_key);

This is placing H(8rA||i)G + B in out_eph_public_key. This is an output key that becomes spendable by the miner. There can be more than one output key (hence this is in a loop and is indexed by i in H(8rA||i)G + B).

Then derive_public_key is H(8*(PvK txsk) || output_i)G + PsK?

Thus, correct.

Do all my assumptions make sense? And is the output of generate_key_derivation a plain public key?

Not quite. generate_key_derivation is creating 8rA (a point), which is then used by derive_public_key to create an output key (or in Monero parlance, a stealth address).

And is the shared secret key the output of hash_to_scalar?

No. hash_to_scalar just takes a hash and converts it to a scalar. The public part of the shared secret is the tx public key, created earlier in construct_miner_tx:

keypair txkey = keypair::generate(hw::get_device("default"));

This is creating r and R (in txkey). The shared part is R which is included in the tx as the tx public key (stuffed into the tx field tx_extra, add_tx_pub_key_to_extra). Only someone with r or a can derive the shared secret aR or rA (as used in the calculations above). The recipient uses aR in their side of the calculations when scanning transactions, to know the transaction is destined for them. r is not stored in the transaction, it is used for the sender-side of the shared secret (rA above).

Hope this helps!

  • Thank you @jtgrassie! Just wanted to clarify, I understand output_index is concatenated into the hash to have the transaction output key uniqueness, what happens if every coinbase transaction has the same transaction output key? Will that be a valid miner transaction? will the reward be given? how is this handled? – jnra Apr 10 '19 at 9:54
  • output_index is the output index within that transaction. It's parameter no in the loop (that is i in H(8rA||i)G + B). Therefore it's always unique within that tx. And thus every output key is globally unique (r is unique to the tx and i to the output). – jtgrassie Apr 10 '19 at 11:55
  • thank you! I was just curious on the part where output_index i is not in play, meaning, there is not such uniqueness(f.e in bitcoin outputs having same address). So is it safe to say that, if an output is not unique, that won't be considered a valid output? thus, not a valid tx? – jnra Apr 10 '19 at 12:58
  • Every output is unique because of r and i. If a duplicate output key was created (manually for example), the tx would get rejected. – jtgrassie Apr 10 '19 at 13:03
  • Thank you again! This totally makes sense. Since I tried to change the derive_public_key() to use the G or the base_point. So right now, my transactions have same output key every a coinbase transaction is mined, at first rewards are given to the miner_address since, that is the first mined block, thus making the first output key as unique, but the 2nd to the n - 1 coinbase tx, all were rejected and I did not get the rewards. Thanks. Sample output of my experiment, when I do show_transfers pastebin.com/WxWvVEEZ – jnra Apr 10 '19 at 13:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.