Coder Social home page Coder Social logo

check-if-output-was-spent's Introduction

Checking which outputs are ours and if they were spent

The example shows how to check which outputs in a given Monero transaction have already been spent. For this purpose, private view and spend keys, as well the corresponding address are required.

Prerequisites

The code was written and tested on Ubuntu 16.04 Beta x86_64.

Instruction for Monero compilation:

The Monero C++ development environment was set as shown in the above link.

C++ code

The main part of the example is main.cpp.

int main(int ac, const char* av[]) {

    // ...
    // argument parsing and processing removed
    // to save some space here

    print("\n\ntx hash          : {} in block no. {}\n\n",
          tx_hash, cryptonote::get_block_height(blk));

    // lets check our keys
    print("private view key : {}\n", private_view_key);
    print("private spend key: {}\n", private_spend_key);
    print("address          : {}\n", address);


    // having our transaction, first we check which output in that
    // transactions are ours. For this we need to go through all outputs
    // in a transaction.

    std::vector<size_t> outputs_ids;

    uint64_t money_transfered {0};

    // look for our outputs in the transaction and the corresponding block reward
    cryptonote::lookup_acc_outs(account_keys, tx, outputs_ids, money_transfered);

    print("money received   : {:0.6f}\n\n\n", money_transfered / 1e12);

    // get tx public key from extras field
    crypto::public_key pub_tx_key = cryptonote::get_tx_pub_key_from_extra(tx);

    vector<crypto::key_image> key_images_found;

    if (outputs_ids.size())
    {
        print("We found our outputs: \n");

        // iterate over each output found
        // and create its key_image.
        //
        // to check if the given output is spend, we just need to check
        // whether the correspoding key_image is present in the blockchain
        for (size_t ouput_i: outputs_ids)
        {
            // get tx output
            const cryptonote::tx_out& tx_output =  tx.vout[ouput_i];

            // get tx output public key
            const cryptonote::txout_to_key& tx_out_to_key
                = boost::get<cryptonote::txout_to_key>(tx_output.target);

            print("Our output: {:s}, amount {:0.6f}\n",
                  tx_out_to_key.key, tx_output.amount / 1e12);

            // public tx key is combined with our private view key
            // to create, so called, derived key.
            // the derived key is used to produce the key_image
            // that we want.
            crypto::key_derivation derivation;

            if (!generate_key_derivation(pub_tx_key, private_view_key, derivation))
            {
                cerr << "Cant get derived key for output with: " << "\n"
                     << "pub_tx_key: " << private_view_key << endl;
                return 1;
            }

            //print("Derived key: {:s}\n", derivation);

            // generate key_image of this output
            crypto::key_image key_image;

            if (!xmreg::generate_key_image(derivation,
                                           ouput_i, /* positoin in the tx */
                                           private_spend_key,
                                           account_keys.m_account_address.m_spend_public_key,
                                           key_image))
            {
                cerr << "Cant generate key image for output: "  << pub_tx_key << endl;
                return 1;
            }

            key_images_found.push_back(key_image);


            print(" - key image generated: {:s}\n", key_image);

        }
    }
    else
    {
        print("No our outputs were found in this transaction\n");
        return 0;
    }

    cout << endl;

    vector<crypto::key_image> spent_key_images;

    // check which of the key_images generated
    // has already been spend
    for (crypto::key_image& key_img: key_images_found)
    {


        // finally check if the key_image generated is present in the blockchain
        bool is_spent = core_storage.have_tx_keyimg_as_spent(key_img);


        if (is_spent)
        {
            spent_key_images.push_back(key_img);
        }

        print("Is output with key_image {:s} spent?: {}\n",
              key_img, is_spent);
    }


    // search for transactions containing key_images generated
    // which were found to be spent. So basically we want to know
    // in which transaction each key was spent.
    if (find_tx && !spent_key_images.empty())
    {

        print("\nSearching for the transactions having the spend keys found ...\n");

        unordered_map<crypto::key_image, crypto::hash> txs_found;

        txs_found = mcore.find_txs_with_key_images(spent_key_images, true);


        if (txs_found.empty())
        {
            cerr << "\nTransactions not found for spend keys O.o?" << endl;
            return 1;
        }

        cout << endl;

        print("The found transactions are:\n");

        // find transactions containing the spent keys found
        for (auto& key_tx: txs_found)
        {

            // key_tx.first is the key_image
            // key_tx.second is the tx hash with the key

            cryptonote::block blk;

            if (!mcore.get_block_by_tx_hash(key_tx.second, blk))
            {
                cerr << "Cant find block for the given transaction" << endl;
                return false;
            }

            uint64_t blk_height = cryptonote::get_block_height(blk);

            print(" - Key image, tx (block height) found: {:s}, {:s} ({:d})\n",
                  key_tx.first, key_tx.second, blk_height);

        }

    }


    cout << "\nEnd of program." << endl;

    return 0;
}

Program options

./checkoutputs -h

checkoutputs, check which outputs in a given tx are ours and if were spent:
  -h [ --help ] [=arg(=1)] (=0)    produce help message
  -t [ --txhash ] arg              transaction hash
  -v [ --viewkey ] arg             private view key string
  -s [ --spendkey ] arg            private spend key string
  -f [ --find-tx ] [=arg(=1)] (=0) find transaction containing key generated if
                                   it is spend (time consuming search)
  -a [ --address ] arg             monero address string
  -b [ --bc-path ] arg             path to lmdb blockchain
  --testnet [=arg(=1)] (=0)        is the address from testnet network

Example result 1

Execute program with default parameters

./checkoutputs
tx hash          : <cda104278309e1637bbe8da841adb25d5d4f541de428e8e3808c83f9a71fe22e> in block no. 985103

private view key : <9c2edec7636da3fbb343931d6c3d6e11bcd8042ff7e11de98a8d364f31976c04>
private spend key: <950b90079b0f530c11801ef29e99618d3768d79d3d24972ff4b6fd9687b7b20c>
address          : <43A7NUmo5HbhJoSKbw9bRWW4u2b8dNfhKheTR5zxoRwQ7bULK5TgUQeAvPS5EVNLAJYZRQYqXCmhdf26zG2Has35SpiF1FP>
money received   : 1.000000


We found our outputs:
Our output: <d09860a6252b68045d8aa790e3d5e9b19341dcd09c6257fdb1e90918bece5b1d>, amount 1.000000
 - key image generated: <ef42203f6a80c7ecc42a6f4c78ecf126696a7f760eb86550bd639acbe7ab5978>

Is output with key_image <ef42203f6a80c7ecc42a6f4c78ecf126696a7f760eb86550bd639acbe7ab5978> spent?: true

Example result 2

Execute program with default parameters, but this time look for transactions which cointain the spent outputs.

./checkoutputs -f
tx hash          : <cda104278309e1637bbe8da841adb25d5d4f541de428e8e3808c83f9a71fe22e> in block no. 985103

private view key : <9c2edec7636da3fbb343931d6c3d6e11bcd8042ff7e11de98a8d364f31976c04>
private spend key: <950b90079b0f530c11801ef29e99618d3768d79d3d24972ff4b6fd9687b7b20c>
address          : <43A7NUmo5HbhJoSKbw9bRWW4u2b8dNfhKheTR5zxoRwQ7bULK5TgUQeAvPS5EVNLAJYZRQYqXCmhdf26zG2Has35SpiF1FP>
money received   : 1.000000


We found our outputs:
Our output: <d09860a6252b68045d8aa790e3d5e9b19341dcd09c6257fdb1e90918bece5b1d>, amount 1.000000
 - key image generated: <ef42203f6a80c7ecc42a6f4c78ecf126696a7f760eb86550bd639acbe7ab5978>

Is output with key_image <ef42203f6a80c7ecc42a6f4c78ecf126696a7f760eb86550bd639acbe7ab5978> spent?: true

Searching for the transactions having the spend keys found ...
	 - checking tx no: 719318/1583736
	 - tx found for key_img: <ef42203f6a80c7ecc42a6f4c78ecf126696a7f760eb86550bd639acbe7ab5978>
	- all keys found! :-)

The found transactions are:
 - Key image, tx (block height) found: <ef42203f6a80c7ecc42a6f4c78ecf126696a7f760eb86550bd639acbe7ab5978>, <2c186ffeb72b26eb17993e81c9590e970c9432494efdb45694c70f3082583e74> (985113)

./checkoutputs -a 41vEA7Ye8Bpeda6g59v5t46koWrVn2PNgEKgzquJjmiKCFTsh9gajr8J3pad49rqu581TAtFGCH9CYTCkYrCpuWUG9GkgeB -v fed77158ec692fe9eb951f6aeb22c3bda16fe8926c1aac13a5651a9c27f34309 -s 1eaa41781d5f880dc69c9379e281225c781a6db8dc544a26008e7a07890afa03 -f -t 1b27f4d6298e0a893609d965092802bef7dbfc40826e92f5957be9cf62d5031b

Example result 3

Test non-spend output.

./checkoutputs -a 41vEA7Ye8Bpeda6g59v5t46koWrVn2PNgEKgzquJjmiKCFTsh9gajr8J3pad49rqu581TAtFGCH9CYTCkYrCpuWUG9GkgeB -v fed77158ec692fe9eb951f6aeb22c3bda16fe8926c1aac13a5651a9c27f34309 -s 1eaa41781d5f880dc69c9379e281225c781a6db8dc544a26008e7a07890afa03 -f -t 1b27f4d6298e0a893609d965092802bef7dbfc40826e92f5957be9cf62d5031b
tx hash          : <1b27f4d6298e0a893609d965092802bef7dbfc40826e92f5957be9cf62d5031b> in block no. 985026

private view key : <fed77158ec692fe9eb951f6aeb22c3bda16fe8926c1aac13a5651a9c27f34309>
private spend key: <1eaa41781d5f880dc69c9379e281225c781a6db8dc544a26008e7a07890afa03>
address          : <41vEA7Ye8Bpeda6g59v5t46koWrVn2PNgEKgzquJjmiKCFTsh9gajr8J3pad49rqu581TAtFGCH9CYTCkYrCpuWUG9GkgeB>
money received   : 0.070000


We found our outputs:
Our output: <ab33da6d8827607f224d775c6fbead998d254db767feca3e8285d30fffbf4d6e>, amount 0.070000
 - key image generated: <d3aee79cc00cdeafd34f5b348780cd1590f6cd004eb37235c6858eab0ec185c9>

Is output with key_image <d3aee79cc00cdeafd34f5b348780cd1590f6cd004eb37235c6858eab0ec185c9> spent?: false

Example result 4

What will be the result if the output (i.e., ab33da6d8827607f224d775c6fbead998d254db767feca3e8285d30fffbf4d6e) from example 3 is spent? For this we just repeat the command and get new results.

./checkoutputs -a 41vEA7Ye8Bpeda6g59v5t46koWrVn2PNgEKgzquJjmiKCFTsh9gajr8J3pad49rqu581TAtFGCH9CYTCkYrCpuWUG9GkgeB -v fed77158ec692fe9eb951f6aeb22c3bda16fe8926c1aac13a5651a9c27f34309 -s 1eaa41781d5f880dc69c9379e281225c781a6db8dc544a26008e7a07890afa03 -f -t 1b27f4d6298e0a893609d965092802bef7dbfc40826e92f5957be9cf62d5031b
tx hash          : <1b27f4d6298e0a893609d965092802bef7dbfc40826e92f5957be9cf62d5031b> in block no. 985026

private view key : <fed77158ec692fe9eb951f6aeb22c3bda16fe8926c1aac13a5651a9c27f34309>
private spend key: <1eaa41781d5f880dc69c9379e281225c781a6db8dc544a26008e7a07890afa03>
address          : <41vEA7Ye8Bpeda6g59v5t46koWrVn2PNgEKgzquJjmiKCFTsh9gajr8J3pad49rqu581TAtFGCH9CYTCkYrCpuWUG9GkgeB>
money received   : 0.070000


We found our outputs:
Our output: <ab33da6d8827607f224d775c6fbead998d254db767feca3e8285d30fffbf4d6e>, amount 0.070000
 - key image generated: <d3aee79cc00cdeafd34f5b348780cd1590f6cd004eb37235c6858eab0ec185c9>

Is output with key_image <d3aee79cc00cdeafd34f5b348780cd1590f6cd004eb37235c6858eab0ec185c9> spent?: true

Searching for the transactions having the spend keys found ...
	 - checking tx no: 306969/1583765
	 - tx found for key_img: <d3aee79cc00cdeafd34f5b348780cd1590f6cd004eb37235c6858eab0ec185c9>
	- all keys found! :-)

The found transactions are:
 - Key image, tx (block height) found: <d3aee79cc00cdeafd34f5b348780cd1590f6cd004eb37235c6858eab0ec185c9>, <75d9a1980294a9c6a96736c8e546b40f6f2640c1fba61853ccd986891c597d31> (1010850)

Example result 5

So now lets check the transaction in which we got our change, i.e., (tx hash: 75d9a1980294a9c6a96736c8e546b40f6f2640c1fba61853ccd986891c597d31) from example 4

./checkoutputs -a 41vEA7Ye8Bpeda6g59v5t46koWrVn2PNgEKgzquJjmiKCFTsh9gajr8J3pad49rqu581TAtFGCH9CYTCkYrCpuWUG9GkgeB -v fed77158ec692fe9eb951f6aeb22c3bda16fe8926c1aac13a5651a9c27f34309 -s 1eaa41781d5f880dc69c9379e281225c781a6db8dc544a26008e7a07890afa03 -f -t 75d9a1980294a9c6a96736c8e546b40f6f2640c1fba61853ccd986891c597d31
tx hash          : <75d9a1980294a9c6a96736c8e546b40f6f2640c1fba61853ccd986891c597d31> in block no. 1010850

private view key : <fed77158ec692fe9eb951f6aeb22c3bda16fe8926c1aac13a5651a9c27f34309>
private spend key: <1eaa41781d5f880dc69c9379e281225c781a6db8dc544a26008e7a07890afa03>
address          : <41vEA7Ye8Bpeda6g59v5t46koWrVn2PNgEKgzquJjmiKCFTsh9gajr8J3pad49rqu581TAtFGCH9CYTCkYrCpuWUG9GkgeB>
money received   : 0.450000


We found our outputs:
Our output: <8c086f9fe0537aef00bc74e8cb912425f34c71b39f5d5d93fb7ba4c3398ffd5d>, amount 0.050000
 - key image generated: <df1504b992cc9fafba99461d7ca53a7a8cac224864ea4d113fcd331b4c2c052e>
Our output: <ada4ed75182403d858ad1fa26bba7f51c20c0f596e920da71fd8961474d6b535>, amount 0.400000
 - key image generated: <79533fc9827883dc9a497d3d7959cee4c232b675103a970b8c98427cf8137fca>

Is output with key_image <df1504b992cc9fafba99461d7ca53a7a8cac224864ea4d113fcd331b4c2c052e> spent?: false
Is output with key_image <79533fc9827883dc9a497d3d7959cee4c232b675103a970b8c98427cf8137fca> spent?: false

The outputs, as expected, havent been spent yet, as we just got them. But we can already see that key images for these ouputs that will be generated when the outputs are going to be spend.

Compile this example

If so then to download and compile this example, the following steps can be executed:

# download the source code
git clone https://github.com/moneroexamples/check-if-output-was-spent.git

# enter the downloaded sourced code folder
cd check-if-output-was-spent

# create the makefile
cmake .

# compile
make

The Monero C++ development environment was set as shown in the following link:

How can you help?

Constructive criticism, code and website edits are always good. They can be made through github.

Some Monero are also welcome:

48daf1rG3hE1Txapcsxh6WXNe9MLNKtu7W7tKTivtSoVLHErYzvdcpea2nSTgGkz66RFP4GKVAsTV14v6G3oddBTHfxP6tU

check-if-output-was-spent's People

Contributors

moneroexamples avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.