6

This question by kenshi84 shows how the pseudoOuts and outPk fields can be validated by anyone (without knowing any of the private keys involved), by checking that sumIn === sumOut:

> var H = ge_scalarmult(cn_fast_hash(ge_scalarmult_base("0100000000000000000000000000000000000000000000000000000000000000")), "0800000000000000000000000000000000000000000000000000000000000000");
undefined
> H
"8b655970153799af2aeadc9ff1add0ea6c7251d54154cfa92c173a0dd39c1f94"
> var fee = swapEndian(d2h256("30000000000"));
undefined
> fee
"00AC23FC06000000000000000000000000000000000000000000000000000000"
> var feeH = ge_scalarmult(H, fee);
undefined
> feeH
"527e4c0b6e34f948fb59ab014ec8eedf9eccfda4930a0b30d12790a0ec0d91f2"
> var pseudoOuts = ["276f03ba8c7852cb545830f7fedcdcd08789675d2a6c265bea236d0de90f6b11", "c611cc551db3b05ad6e5dba4ce89a8eeeb18317d8b565031941e98b6b9b8db4f", "8a088f1ccd11dd1633a663538faa9cb18c157b4fd37c421697a6356b4d7a98f6", "9e1238add1c1a4712904e5d5d8913482dcd6d31af166bc73918fd8148a42f22b"];
undefined
> var outPk = [ "f9cabc6b0fd32822feb3e13c70b54b2cdc2a3ce7c88ac661c29ab20732e2974f", "cfb010382648e11d7d5744fe8051c8606f31c901f9ede5b7e392f73790f9e7f8"]
undefined
> var sumIn = ge_add(ge_add(ge_add(pseudoOuts[0], pseudoOuts[1]), pseudoOuts[2]), pseudoOuts[3]);
undefined
> var sumOut = ge_add(ge_add(outPk[0], outPk[1]), feeH);
undefined
> sumIn
"a340fb56b64d831d4f06079f1fc4d507a7a2d1b0107ea7814c626c7394190da6"
> sumOut
"a340fb56b64d831d4f06079f1fc4d507a7a2d1b0107ea7814c626c7394190da6"

It's nice to have working javascript code (you can try by opening a browser console here), and I wonder if my question can be answered in a similar way.

I've noticed that the ecdhInfo field wasn't used in the above javascript code. Is there a way to validate ecdhInfo too, without knowing any private keys? Or is this not necessary?

For reference, here's rct_signatures from kenshi84's question again:

{
    "type": 2, 
    "txnFee": 30000000000, 
    "pseudoOuts":["276f03ba8c7852cb545830f7fedcdcd08789675d2a6c265bea236d0de90f6b11", "c611cc551db3b05ad6e5dba4ce89a8eeeb18317d8b565031941e98b6b9b8db4f", "8a088f1ccd11dd1633a663538faa9cb18c157b4fd37c421697a6356b4d7a98f6", "9e1238add1c1a4712904e5d5d8913482dcd6d31af166bc73918fd8148a42f22b"], 
    "ecdhInfo": [ {
        "mask": "c626b75f726e88a26fc74c1bb508fa9358c0896a7635d0f1256c7f43f0217706", 
        "amount": "63c1d97047ff515ccd5ca271f4e5013b9c1092c25307207a0ff037b13f492c00"
      }, {
        "mask": "73b4367f9b143c0a453598f85761698c4548e890fa52a05b4e28183126525008", 
        "amount": "81b48b46e79b458a234ad36d3d0890f89e30d50cc18a687dd94fd0ef3417da0f"
      }], 
    "outPk": [ "f9cabc6b0fd32822feb3e13c70b54b2cdc2a3ce7c88ac661c29ab20732e2974f", "cfb010382648e11d7d5744fe8051c8606f31c901f9ede5b7e392f73790f9e7f8"]
 }

1 Answers1

4

Both the ecdhInfo mask and amount are encrypted by the sender of the transaction.

Both are encrypted (each in a slightly different way) using the transaction's shared secret (aR).

Therefore both encrypted values will be randomly distributed, and thus cannot be validated by a third party.

If the sender of the transaction had somehow written faulty values into the transaction, the only consequence would be that the outputs created by the transaction would be unspendable.

The code that encrypts and decrypts the ecdhInfo values is here: https://github.com/monero-project/monero/blob/2b00899bb28e09f0c44813689acc0add73832215/src/ringct/rctOps.cpp#L447

knaccc
  • 8,518
  • 17
  • 23