A similar question has been asked here [1], but it is still unclear to me so far...

I'm looking for the specific part of computing the formula:

P = Hs(rA)G + B

I've been lost my way while looking at [2] since the structs and the names of the functions are not well clear and documented.


[1]-Where is the code that generates stealth addresses and matches them with view keys?

[2]-https://github.com/monero- project/monero/blob/102a51bcd48a3cd2cb794aab7dbe243393f155b3/src/cryptonote_core/cryptonote_tx_utils.cpp#L197

1 Answer 1


The implementation of that white paper formula is actually P = Hs(8rA || i)G+B.

The 8 is there to force the rA EC point to be in the group of the base point G, even when A is a malicious point which is not in the base point group (i.e. is not a multiple of G).

The || symbol means byte concatenation, i.e. concatenate the bytes of the compressed representation of the EC point 8rA with a varint byte representation of the output index i. The output index is appended so that multiple outputs to the same recipient won't have identical public keys (which would be a disaster, because then they'd also share the same key image and only one of them would be able to be spent).

On this line you'll see a call to generate_key_derivation: https://github.com/monero-project/monero/blob/102a51bcd48a3cd2cb794aab7dbe243393f155b3/src/cryptonote_core/cryptonote_tx_utils.cpp#L393

The generate_key_derivation method calculates the 8rA part using ge_scalarmult to calculate the rA part and using ge_mul8 to turn that into 8rA.

On this line you'll see a call to derive_public_key https://github.com/monero-project/monero/blob/102a51bcd48a3cd2cb794aab7dbe243393f155b3/src/cryptonote_core/cryptonote_tx_utils.cpp#L408

The derive_public_key method takes the already calculated 8rA, uses the derivation_to_scalar method (which in turn uses the hash_to_scalar method) to produce Hs(8rA || i), and then uses ge_scalarmult_base to multiply it by G to get Hs(8rA || i)G. Finally it adds B to get the final result Hs(8rA || i)G+B.

You'll see some confusing methods like ge_p3_to_cached and ge_p1p1_to_p2 etc. This is because the most efficient way of performing different operations on EC points is to convert them into different representations prior to particular operations. For more information, see "Faster Addition and Doubling on Elliptic Curves" https://cr.yp.to/talks/2007.12.03/slides.pdf

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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