15

Even though I fully trust the math behind RingCT and I know no moneroj can be created out of thin air, sometimes I'd like to see for myself the consistency of the Pedersen Commitment before/after any given transaction (ie. they sum up to the same value).

If I do print_tx 914b3d1367f10ee95e4aad793e07dab20c2c7106c63593821d7300a7a4cb1a34 on the testnet, I see some information among quite a chunk of data:

Found in blockchain at height 834232
...(chunk)...
{
  "version": 2, 
  "unlock_time": 0, 
  "vin": [ {
      "key": {
        "amount": 0, 
        "key_offsets": [ 13206, 10439, 3501, 19878, 1840
        ], 
        "k_image": "85e8e93b7dcee586a427f7892d42e9d6127231261ee794bed0b0a17d3de4df38"
      }
    }, {
      "key": {
        "amount": 0, 
        "key_offsets": [ 41271, 5033, 2562, 21, 95
        ], 
        "k_image": "0606c5bdb3f04cf602a1a50b76253b4fac1f86aa283ecae56af05eeab361cf2f"
      }
    }, {
      "key": {
        "amount": 0, 
        "key_offsets": [ 19118, 15576, 2754, 6750, 4652
        ], 
        "k_image": "68b8fa419a663433d4aac7cb807905fa4adf94873da346578a82ed9091a09f8f"
      }
    }, {
      "key": {
        "amount": 0, 
        "key_offsets": [ 22933, 15530, 3305, 5886, 1244
        ], 
        "k_image": "d8fe30c97b13beed710b2609dc1ce06e85b08a741fb7d7a5960810ff5de47a7e"
      }
    }
  ], 
  "vout": [ {
      "amount": 0, 
      "target": {
        "key": "5cde923e1712422d71dd577b35681125912b4c4a538444193ab6e271fd7a43a8"
      }
    }, {
      "amount": 0, 
      "target": {
        "key": "ca3cc9d51a037322e3f3ff2fe771e85c26628b7e2c1163c3e1e29515885c4163"
      }
    }
  ], 
  "extra": [ 1, 235, 1, 181, 37, 243, 100, 198, 158, 197, 43, 164, 39, 167, 190, 249, 250, 228, 251, 153, 212, 248, 165, 112, 95, 210, 238, 138, 151, 158, 243, 238, 50
  ], 
  "rct_signatures": {
    "type": 2, 
    "txnFee": 30000000000, 
    "pseudoOuts": [ "276f03ba8c7852cb545830f7fedcdcd08789675d2a6c265bea236d0de90f6b11", "c611cc551db3b05ad6e5dba4ce89a8eeeb18317d8b565031941e98b6b9b8db4f", "8a088f1ccd11dd1633a663538faa9cb18c157b4fd37c421697a6356b4d7a98f6", "9e1238add1c1a4712904e5d5d8913482dcd6d31af166bc73918fd8148a42f22b"], 
    "ecdhInfo": [ {
        "mask": "c626b75f726e88a26fc74c1bb508fa9358c0896a7635d0f1256c7f43f0217706", 
        "amount": "63c1d97047ff515ccd5ca271f4e5013b9c1092c25307207a0ff037b13f492c00"
      }, {
        "mask": "73b4367f9b143c0a453598f85761698c4548e890fa52a05b4e28183126525008", 
        "amount": "81b48b46e79b458a234ad36d3d0890f89e30d50cc18a687dd94fd0ef3417da0f"
      }], 
    "outPk": [ "f9cabc6b0fd32822feb3e13c70b54b2cdc2a3ce7c88ac661c29ab20732e2974f", "cfb010382648e11d7d5744fe8051c8606f31c901f9ede5b7e392f73790f9e7f8"]
  }, 
  "rctsig_prunable": {
    "rangeSigs": [ {
...(chunk)...

I guess key_offsets point to the outputs P_i^j and outPk represent the output commitments C_{i,out} as in MRL-0005 (page 9, Definition 4.1). What I would like to do is to check that i-th member of R actually matches \sum_{j}P_i^j + \sum_{j}C_i^j - \sum_{k}C_{k,out}. Can I do this by myself easily, eg. by using Luigi1111's JavaScript code? How can I get P_i^j and C_i^j and i-th member of R from the daemon?

Also, what do pseudoOuts represent?

  • 1
    As far as I know, pseudoOuts are the "decoy" outputs used for the ring signature. In your example there are 4 pseudoOuts, which corresponds to the minimum mixin of 4 that is enforced on testnet. – dEBRUYNE Nov 12 '16 at 11:36
  • @dEBRUYNE Thanks for answering. How are these "decoy outputs" used in the ring signature? I don't find this term in MRL-0005. – kenshi84 Nov 13 '16 at 7:28
9

As in my post to MRL Issue #6, I now figured out what pseudoOuts mean. Assuming the outPk means the output commitments, what I'd like to know (assuming the ring signature is valid), would be to see the following hold:

sum_j{pseudoOuts[j]} = sum_i{outPk[i]} + fee*H

What I'm missing in Luigi's JS code is a way to get fee*H.

Edit: Luigi kindly answered my question! Here's the full JS code you can try at: https://xmr.llcoins.net/

> 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"
  • 1
    fee*H should be easy to do in the JS (I assume you're using a browser console to access it?). You can generate H with var H = generate_key_derivation_2(cn_fast_hash(sec_key_to_pub("0100000000000000000000000000000000000000000000000000000000000000")), "0800000000000000000000000000000000000000000000000000000000000000");. Then convert the fee in AU to a 32byte string and scalarmult with something like var feeH = generate_key_derivation_2(H, swapEndian(("0000000000000000000000000000000000000000000000000000000000000000" + parseInt(<your AU fee here>).toString(16)).slice(-64))); – Luigi Nov 29 '16 at 21:57
  • 1
    I like it a lot. :) Since you exposed my, uh, dumb function names (or was that me), I renamed/aliased some of them. ge_scalarmult is now the name for generate_key_derivation_2 (both still work) and ge_scalarmult_base now also works for sec_key_to_pub. I also added a new d2h256 conversion function to convert any size decimal value to padded hex. – Luigi Nov 30 '16 at 1:25
  • Thanks, I replaced some function names! Your function d2h256 seems to give me the hex string in the wrong order: 00000000000000000000000000000000000000000000000000000006FC23AC00 – kenshi84 Nov 30 '16 at 3:58
  • Yes it's big endian like "normal" numbers. If you check the function, there's a comment right above it explaining as such. :) – Luigi Nov 30 '16 at 15:49

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.