# Where are the input keys stored for a transaction (understanding vin field)

I am currently implementing the heuristic 1 algorithm from this paper https://eprint.iacr.org/2017/338.pdf for a university project. (pretty interesting btw worth reading :) ).

My problem currently is, I don't fully understand the `vin` field, which I need for the algorithm.

So what I know:

The `vin` field contains all input transactions for the whole transaction.

Example would be a `vin` field containing 3 inputs, this 3 inputs represent the denominations of the full transaction amount.

Each of this 3 inputs has also a `key_image` field. It is there for double spending reasons. Each `key_image` exists only once on the blockchain. For simplicity we say `key_image = HASH(key_offset)`, where `key_offset` is the public key of the real spender in this `vin input`.

The values in `key_offsets` are: The public key of the spender + the mixins used. So `key_offsets_size = spender_key + N * mixin_key`.

I also know that `key_offsets` are stored differentially, meaning `key_offsets = [1,1,1] => real index of inkeys: [1,2,3]`.

So I am pretty confused how it can be that the same index in `key_offsets` can be more than once on the blockchain.

For example I querried block X and I had `key_offsets = [ 1 ]`, then I querried block Y (Y > X) and got the same `key_offsets`.

What am I missing here? Where are "the real" input keys stored and how can I acquire them? Would be awesome if someone could point me on the correct API call.

UPDATE:

For example I queried block `345` and `1247`. Got tx `9ecdadf8b95aa0a7b754559f5fd7a9bb0f5014c4107b3dc6b3331430b5ea984d` in `345` and `ed4717dd86e5b033c36df3b41a3a5296f392e3524651c79792e9b39674c7f1ef` in `1247`.

When I get all the denominations from `345`:

``````{
"key":
{
"amount": 458444,
"k_image": "2c03aa742e881a41588827ea8680f68ea3e6988917c832767e951f3ff7457b17",
"key_offsets": [
0
]
}
},
``````

and for `1247`:

``````{
"key":
{
"amount": 307304,
"k_image": "fca0574448356fedf7493310fba22a717c0c7bd7f4acca03fb17bb8d582eb5ef",
"key_offsets": [
0
]
}
},
``````

So for each output you spend, you provide a set of key offsets, one of which will be yours...

This should mean that both txs use the tx with the index 0 as mixin. But there is only 1 offset present in the transactions meaning that the index 0 is the transaction itself.

So I am pretty confused how it can be that the same index in key_offsets can be more than once on the blockchain.

Let's take a step back.

Every output created (i.e. once mined, added to the blockchain), has a global index (its key offset).

Every transaction spends previously created outputs - it uses outputs as inputs to fund the transaction.

Now, when you create a transaction, for each output you own and are spending (so using as an input), you mix with other decoy outputs (other outputs on the blockchain, not owned by yourself). Collectively this is a set of key offsets (the global index of each output on the blockchain that is a member of this collection).

So for each output you spend, you provide a set of key offsets, one of which will be yours, the rest other peoples. This of course means other people creating transactions can also include your owned output indices in their set of key offsets.

As an observer, you can look at any given set of key offsets in a transaction, but have no idea which is the one actually being spent. Therefore, the fact you may see a particular output index in several different transactions, you have no way of knowing which, if any, of the transactions, are actually spending it.

Where are "the real" input keys stored and how can I acquire them?

If this is not clear from above, the input keys are stored on the blockchain. Each actual key is a previously created output and can be referenced (looked up), using its global index (key offset). You can use the daemon RPC command get_outs to obtain the actual key for an index. E.g. (on testnet here):

```\$ curl -X POST http://127.0.0.1:28081/get_outs -H 'Content-Type: application/json' \
-d '{"outputs":[{"index":127232}]}'
{
"outs": [{
"height": 877775,
"key": "3ab3f615dc7ee403d753f3c3604afe57af3bff62f2d95ae74c3ca5603295811c",
"txid": "0000000000000000000000000000000000000000000000000000000000000000",
"unlocked": true
}],
"status": "OK",
"untrusted": false
}
```

UPDATE

Everything above relates to the current transaction version, v2 (i.e. RingCT), which covers the vast majority of Monero transactions. The question however has since been been updated to include references to pre-RingCT transactions as it now mentions heights 345 and 1247, so it's worth noting the following from the v1 transaction spec, section 3.2.2:

``````  - key_offsets: The list of offsets in the global array of outputs
of type txout_to_key having the same amount as the input. The
first value is the ordinal number of the first referenced output
among those having the same amount. Each of the following values
is the offset of the next referenced output relative to the
previous one. One of the outputs referenced is the actual output
being spent, but only the sender known which one it is. The array
of the corresponding public keys is a part of one-time ring
signature verification algorithm input [CNS002].
``````

To lookup a v1 key from its offset, you must also provide the amount field, because as the spec states:

``````  The first value is the ordinal number of the first referenced output
among those having the same amount.
``````

And therefore the RPC command to lookup, includes the amount:

```\$ curl -X POST http://127.0.0.1:18081/get_outs -H 'Content-Type: application/json' \
-d '{"outputs":[{"index":0,"amount":307304}]}'
{
"outs": [{
"height": 1123,
"key": "45519224a687ec4fbb2675de996d4e3d8e8de8f32b7d6a57d6372f2f96908794",
"txid": "0000000000000000000000000000000000000000000000000000000000000000",
"unlocked": true
}],
"status": "OK",
"untrusted": false
}
```

Therefore:

This should mean that both txs use the tx with the index 0 as mixin.

As you referenced txs in blocks 345 and 1247, these are v1 transactions. The output at index 0 for amount 307304, is not the same as the output at index 0 for amount 458444. They are different outputs.

• Thank you for your answer. So what I am thinking is right. The `key_offsets` are indeed the inputs for my tx. BUT as I mentioned in my example I read multiple transactions where the whole `key_offsets` vector was the same. Meaning I had a `vector1 = [1] and a vector2 = [1]` from 2 different transactions, meaning the included inputs are the same. And since no mixins were used here (size=1) I definently know that this key is spend. This is the basis of the deannonymisation attack I am implementing. But you still answered the most needed part of my question. Aug 17, 2019 at 21:08
• I've updated the answer based on your updated question which now references v1 transactions. Aug 18, 2019 at 0:34
• Now this all makes sense. Thank you very much. Yes indeed I am only interested in tx before block 1.400.000 (before RingCT enforce). Your answer was very good and well explained, I wish I could upvote it more times. Aug 18, 2019 at 12:36
• Glad I could help. Aug 18, 2019 at 13:56