2

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.

jtgrassie
  • 19,601
  • 4
  • 17
  • 54
jnra
  • 69
  • 4

1 Answers1

2

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?

Correct.

Then:

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!

jtgrassie
  • 19,601
  • 4
  • 17
  • 54