Author

Topic: bitcoind/bitcoin-qt find source address of input (Read 2292 times)

newbie
Activity: 32
Merit: 0
ok so my previous example was good for wallet transactions..  so instead I made a more "general" implementation for it to be in getrawtransaction of the bitcoin client

here is a patch-like mod of the code of TxToJSON in rpcrawtransaction.cpp which is used to output a verbosed version of getrawtransaction or decoderawtransaction:
(added code has + in front)

Code:
void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
{
    entry.push_back(Pair("txid", tx.GetHash().GetHex()));
    entry.push_back(Pair("version", tx.nVersion));
    entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime));
    Array vin;
    BOOST_FOREACH(const CTxIn& txin, tx.vin)
    {
        Object in;
        if (tx.IsCoinBase())
            in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
        else
        {
            in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
            in.push_back(Pair("vout", (boost::int64_t)txin.prevout.n));
+           CTransaction txPrev;
+           uint256 hashBlock;
+           GetTransaction(txin.prevout.hash, txPrev, hashBlock);  // get the vin's previous transaction
+           CTxDestination source;
+           if (ExtractDestination(txPrev.vout[txin.prevout.n].scriptPubKey, source))  // extract the destination of the previous transaction's vout[n]
+           {
+               CBitcoinAddress addressSource(source);              // convert this to an address
+               in.push_back(Pair("address",addressSource.ToString())); // add the address to the returned object
+           }
            Object o;
            o.push_back(Pair("asm", txin.scriptSig.ToString()));
            o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
            in.push_back(Pair("scriptSig", o));
        }
        in.push_back(Pair("sequence", (boost::int64_t)txin.nSequence));
        vin.push_back(in);
    }
    entry.push_back(Pair("vin", vin));
    Array vout;
    for (unsigned int i = 0; i < tx.vout.size(); i++)
    {
        const CTxOut& txout = tx.vout[i];
        Object out;
        out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
        out.push_back(Pair("n", (boost::int64_t)i));
        Object o;
        ScriptPubKeyToJSON(txout.scriptPubKey, o);
        out.push_back(Pair("scriptPubKey", o));
        vout.push_back(out);
    }
    entry.push_back(Pair("vout", vout));

    if (hashBlock != 0)
    {
        entry.push_back(Pair("blockhash", hashBlock.GetHex()));
        map::iterator mi = mapBlockIndex.find(hashBlock);
        if (mi != mapBlockIndex.end() && (*mi).second)
        {
            CBlockIndex* pindex = (*mi).second;
            if (pindex->IsInMainChain())
            {
                entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight));
                entry.push_back(Pair("time", (boost::int64_t)pindex->nTime));
                entry.push_back(Pair("blocktime", (boost::int64_t)pindex->nTime));
            }
            else
                entry.push_back(Pair("confirmations", 0));
        }
    }
}
kjj
legendary
Activity: 1302
Merit: 1026
I'm only interested in the address.. not the owner.. 
I know this will not always resolve to an address.. but in most case it will.. I will just catch the errors of when it is not the case and handle it gracefully

Good to hear.  Sounded like you were working on a website, but I like to give that reminder in these threads, so that when people go searching and find out how you did it, they also find out that it might not do what they expect.
newbie
Activity: 32
Merit: 0
Just as a reminder, while this like it should work, the concept of a sending address does not exist in bitcoin.  What this is doing is finding the last address to have received these funds.  This is occasionally what you expect, but not always.  If you are thinking that this address is owned or controlled by the person that sent you a transaction, you will be wrong fairly often.

I'm only interested in the address.. not the owner.. 
I know this will not always resolve to an address.. but in most case it will.. I will just catch the errors of when it is not the case and handle it gracefully
kjj
legendary
Activity: 1302
Merit: 1026
Just as a reminder, while this like it should work, the concept of a sending address does not exist in bitcoin.  What this is doing is finding the last address to have received these funds.  This is occasionally what you expect, but not always.  If you are thinking that this address is owned or controlled by the person that sent you a transaction, you will be wrong fairly often.
newbie
Activity: 32
Merit: 0
Ok from the help of the people on freenode/bitcoin-dev I was able to resolve the addresses from the inputs of a transaction using the vin.prevout

so just for other people to know...  exmaple to find out the first input's address

Code:
CWalletTx wtx;
pwalletMain->GetTransaction(uint256(txid), wtx);     // get current transaction
CTxIn vin = wtx.vin[0];                                        //get first input
CWalletTx wtxPrev;                                     
pwalletMain->GetTransaction(vin.prevout.hash, wtxPrev);    // get the vin's previous transaction
CTxDestination source;
ExtractDestination(wtxPrev.vout[vin.prevout.n].scriptPubKey, source);  // extract the destination of the previous transaction's vout[n]
CBitcoinAddress addressSource(source);                // convert this to an address

print addressSource.ToString() // might as well print it!

newbie
Activity: 32
Merit: 0
Im trying to find the input address of a transaction but i can't seem to find out how..  anyone ?

Transactions do not have an input address.

They have one or more inputs, which may or may not correspond to one or more addresses.

If you have a CScript, then you can call:
Code:
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector& addressRet, int& nRequiredRet);

What are you trying to do?


Im just trying to output more info on the getrawtransaction rpc command for my personal bitcoins ...

lets say i have this transaction output (testnet):
Code:
{
    "hex" : "0100000001241514a48241f8af8abde6e6e3a657a6ff67beb2febdd5c1f4c62a71a1fb81c3000000008b483045022100a84c1b1a89938c4b16ec7749e9afc16f1a5ec26ddbb16e44739818f4bb85b74c02205d5ce610e0b9d80a373f305dbe67d7347d47470e4b3f6bd98e670ae511d98b920141043ac715efdea8815afc64d7441549e9114ba5d2658f0dcc1a75a8420e8af4791ad8ac46b2eec0463bc54946662e860717d92afe137f0a9fb1b7e1eea812487285ffffffff0200a3e111000000001976a9144988abbeb751dcd6e9f4ec40d50b84c99ed1426d88ac00c2eb0b000000001976a914539862a4bc81786df288265752e12bd7c0c0a6c488ac00000000",
    "txid" : "6aeb3de625830fcc45f675042e1ed98d2c08af72119f81a6e7819d55a6f8ab83",
    "version" : 1,
    "locktime" : 0,
    "vin" : [
        {
            "txid" : "c381fba1712ac6f4c1d5bdfeb2be67ffa657a6e3e6e6bd8aaff84182a4141524",
            "vout" : 0,
            "scriptSig" : {
                "asm" : "3045022100a84c1b1a89938c4b16ec7749e9afc16f1a5ec26ddbb16e44739818f4bb85b74c02205d5ce610e0b9d80a373f305dbe67d7347d47470e4b3f6bd98e670ae511d98b9201 043ac715efdea8815afc64d7441549e9114ba5d2658f0dcc1a75a8420e8af4791ad8ac46b2eec0463bc54946662e860717d92afe137f0a9fb1b7e1eea812487285",
                "hex" : "483045022100a84c1b1a89938c4b16ec7749e9afc16f1a5ec26ddbb16e44739818f4bb85b74c02205d5ce610e0b9d80a373f305dbe67d7347d47470e4b3f6bd98e670ae511d98b920141043ac715efdea8815afc64d7441549e9114ba5d2658f0dcc1a75a8420e8af4791ad8ac46b2eec0463bc54946662e860717d92afe137f0a9fb1b7e1eea812487285"
            },
            "sequence" : 4294967295
        }
    ],
    "vout" : [
        {
            "value" : 3.00000000,
            "n" : 0,
            "scriptPubKey" : {
                "asm" : "OP_DUP OP_HASH160 4988abbeb751dcd6e9f4ec40d50b84c99ed1426d OP_EQUALVERIFY OP_CHECKSIG",
                "hex" : "76a9144988abbeb751dcd6e9f4ec40d50b84c99ed1426d88ac",
                "reqSigs" : 1,
                "type" : "pubkeyhash",
                "addresses" : [
                    "mnDmM7j73HEqo746F1cLQZXwTXNPzLxc3W"
                ]
            }
        },
        {
            "value" : 2.00000000,
            "n" : 1,
            "scriptPubKey" : {
                "asm" : "OP_DUP OP_HASH160 539862a4bc81786df288265752e12bd7c0c0a6c4 OP_EQUALVERIFY OP_CHECKSIG",
                "hex" : "76a914539862a4bc81786df288265752e12bd7c0c0a6c488ac",
                "reqSigs" : 1,
                "type" : "pubkeyhash",
                "addresses" : [
                    "mo8xvtom7uyCwjh3MHzjdc8ZtWqAQp6xW7"
                ]
            }
        }
    ],
    "blockhash" : "00000000235841896dc9856e8a3ef214df8f5e4f2127e534ff18199616f8da00",
    "confirmations" : 103,
    "time" : 1349331390,
    "blocktime" : 1349331390
}

well i would like it to display the vin's address ... a bit like what blockchain.info displays!
legendary
Activity: 1652
Merit: 2311
Chief Scientist
Im trying to find the input address of a transaction but i can't seem to find out how..  anyone ?

Transactions do not have an input address.

They have one or more inputs, which may or may not correspond to one or more addresses.

If you have a CScript, then you can call:
Code:
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector& addressRet, int& nRequiredRet);

What are you trying to do?
newbie
Activity: 32
Merit: 0
Im trying to find the input address of a transaction but i can't seem to find out how..  anyone ?

Code:
CWalletTx wtx;
pwalletMain->GetTransaction(uint256(txid), wtx);
CTxIn vin = wtx.vin[0];
CScript scriptSig = vin.scriptSig;

how can I get the source address of that vin .. I dont seem to understand how I can get the address of the scriptsig ..


Jump to: