After the receiver scan the blockchain and identifies his own transaction, how does he know the amount that he received in that Tx? (Without off-chain communication)

I appreciate a Technical explanation according to the Monero terminology (RingCT etc..).


1 Answer 1


The amount is encrypted by the sender and then communicated as part of the transaction (it's a field called amount in the ecdhInfos part of the transaction).

To decrypt the encrypted amount, you need to know your private view key a. The transaction already includes the transaction public key R.

Decrypted amount = encrypted amount - Hs(Hs(8aR || i)) where i is the index of the output whose amount you want to decrypt, || means byte concatenation, and Hs() is a hashing function that returns a kind of number called a scalar.


In order to reduce the storage required for the encrypted amount from 32 bytes to 8 bytes, the scheme is now:

decrypted_amount = 64-bit encrypted amount XOR first 8 bytes of keccak("amount" || Hs(8aR || i))
  • 1
    1- How does it make sense to subtract hash values from encrypted data? 2- How does the receiver know 'i' value? 3-Why is there 8 inside the hash function? Commented Mar 8, 2018 at 9:32
  • 1. It's a nice way of encrypting the value, since the hash will be randomly distributed, meaning the encrypted amount will be randomly distributed. You're seeing the reverse operation to decrypt it. 2. i is just the index of the output, and is simply the array index of the output as listed in the transaction 3. The cryptonote white paper says the transaction shared secret is aR, but in reality it's 8aR in the implementation in order to ensure that the resulting EC point is in the subgroup of G and not in a small subgroup (which would cause a vulnerability).
    – knaccc
    Commented Mar 12, 2018 at 20:24
  • Why is it hashed twice? Commented Apr 20, 2019 at 13:27
  • @WeCanBeFriends because Hs(8aR || i) is already the per-output shared secret, and we want a different shared secret to encrypt the amount. Note that this scheme has changed recently, in order to reduce the storage required to 64 bits per amount. Now we have decrypted_amount = encrypted amount XOR keccak("amount" || Hs(8aR || i)). See github.com/monero-project/monero/blob/…
    – knaccc
    Commented Apr 22, 2019 at 18:16

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.