3

I'm trying to determine the source address of transactions for automated refunding, but I'm seeing unexpected output from Bitcoin-QT

The transaction in question on blockexplorer: 8bc80f72d9cc6fecda77138e7364f95b48d652db404889deafd48158dc46387e

And below is the result of bitcoind gettransaction for the same txid. Shouldn't I see the same thing? Or is there some issue with inter-wallet sending?

{
"amount" : 0.00000000,
"fee" : -0.00010000,
"confirmations" : 1,
"blockhash" : "0000000000941dab82b8f78596f93832104288c85e7951b5f505b8c1c30dd4ba",
"blockindex" : 1,
"blocktime" : 1377648593,
"txid" : "8bc80f72d9cc6fecda77138e7364f95b48d652db404889deafd48158dc46387e",
"time" : 1377648549,
"timereceived" : 1377648549,
"details" : [
    {
        "account" : "",
        "address" : "n1SrgGXRGjK2gKcvSDRVUDPA1aVKBaG6PQ",
        "category" : "send",
        "amount" : -0.10000000,
        "fee" : -0.00010000
    },
    {
        "account" : "",
        "address" : "mtjmGtkZet4Y7rzQrC8cweuJMYGZFpPw4d",
        "category" : "send",
        "amount" : -0.10000000,
        "fee" : -0.00010000
    },
    {
        "account" : "",
        "address" : "n4N4hQZK1sgHv8z3ikHsuN98vGNhshQZSo",
        "category" : "send",
        "amount" : -0.10000000,
        "fee" : -0.00010000
    },
    {
        "account" : "",
        "address" : "mvw4DVoSL7APFGdHb2RGYebzBKDBankTAM",
        "category" : "send",
        "amount" : -0.99950000,
        "fee" : -0.00010000
    },
    {
        "account" : "account1",
        "address" : "n1SrgGXRGjK2gKcvSDRVUDPA1aVKBaG6PQ",
        "category" : "receive",
        "amount" : 0.10000000
    },
    {
        "account" : "account2",
        "address" : "mtjmGtkZet4Y7rzQrC8cweuJMYGZFpPw4d",
        "category" : "receive",
        "amount" : 0.10000000
    },
    {
        "account" : "account3",
        "address" : "n4N4hQZK1sgHv8z3ikHsuN98vGNhshQZSo",
        "category" : "receive",
        "amount" : 0.10000000
    },
    {
        "account" : "account4",
        "address" : "mvw4DVoSL7APFGdHb2RGYebzBKDBankTAM",
        "category" : "receive",
        "amount" : 0.99950000
    }
]
}

Edit: And here is the result of combining getrawtransaction and decoderawtransaction:

{
"txid" : "8bc80f72d9cc6fecda77138e7364f95b48d652db404889deafd48158dc46387e",
"version" : 1,
"locktime" : 0,
"vin" : [
    {
        "txid" : "f96590f6db1e8748f349e93ae5e1e335c57d55df9a26a70f99e7c06b32538f16",
        "vout" : 0,
        "scriptSig" : {
            "asm" : "304502201d7a5a31936d9a4a0ff17f357dda13e87d7459a7663d127da783865858b552c5022100bac9edf373d42c578c92231cc096a620baa174d7bf141c519047b3ca5dc3577101 03f5fd9f5ad8f4a5ac11c9c8e6f6b094129dbc3d8a9f753dc8d415c5c42a5cccfa",
            "hex" : "48304502201d7a5a31936d9a4a0ff17f357dda13e87d7459a7663d127da783865858b552c5022100bac9edf373d42c578c92231cc096a620baa174d7bf141c519047b3ca5dc35771012103f5fd9f5ad8f4a5ac11c9c8e6f6b094129dbc3d8a9f753dc8d415c5c42a5cccfa"
        },
        "sequence" : 4294967295
    }
],
"vout" : [
    {
        "value" : 0.10000000,
        "n" : 0,
        "scriptPubKey" : {
            "asm" : "OP_DUP OP_HASH160 da9c29ba563c33688e8e1d85b84a634a271b5282 OP_EQUALVERIFY OP_CHECKSIG",
            "hex" : "76a914da9c29ba563c33688e8e1d85b84a634a271b528288ac",
            "reqSigs" : 1,
            "type" : "pubkeyhash",
            "addresses" : [
                "n1SrgGXRGjK2gKcvSDRVUDPA1aVKBaG6PQ"
            ]
        }
    },
    {
        "value" : 0.10000000,
        "n" : 1,
        "scriptPubKey" : {
            "asm" : "OP_DUP OP_HASH160 9105d7f92fd467f0035cd4b5b58bea1167647618 OP_EQUALVERIFY OP_CHECKSIG",
            "hex" : "76a9149105d7f92fd467f0035cd4b5b58bea116764761888ac",
            "reqSigs" : 1,
            "type" : "pubkeyhash",
            "addresses" : [
                "mtjmGtkZet4Y7rzQrC8cweuJMYGZFpPw4d"
            ]
        }
    },
    {
        "value" : 0.10000000,
        "n" : 2,
        "scriptPubKey" : {
            "asm" : "OP_DUP OP_HASH160 fa9c7e784bfae5e3d330cba28b73c804da71f213 OP_EQUALVERIFY OP_CHECKSIG",
            "hex" : "76a914fa9c7e784bfae5e3d330cba28b73c804da71f21388ac",
            "reqSigs" : 1,
            "type" : "pubkeyhash",
            "addresses" : [
                "n4N4hQZK1sgHv8z3ikHsuN98vGNhshQZSo"
            ]
        }
    },
    {
        "value" : 0.99950000,
        "n" : 3,
        "scriptPubKey" : {
            "asm" : "OP_DUP OP_HASH160 a918d01415a09ee82034f1dce3217741dcdf5849 OP_EQUALVERIFY OP_CHECKSIG",
            "hex" : "76a914a918d01415a09ee82034f1dce3217741dcdf584988ac",
            "reqSigs" : 1,
            "type" : "pubkeyhash",
            "addresses" : [
                "mvw4DVoSL7APFGdHb2RGYebzBKDBankTAM"
            ]
        }
    }
]
}

Here's a reference stating the only way is to identify the output index of the previous transaction: https://bitcoin.stackexchange.com/a/12472/3413

If this is accurate, then to determine the "refund" address of a particular transaction, you would have to run the following pseudocode?:

txhex = getrawtransaction(targettxhash)
txjson = decoderawtransaction(txhex)
foreach txinput in txjson.vin:
  txhexprev = getrawtransaction(txinput.txid)
  txjsonprev = decoderawtransaction(txhexprev)
  foreach txprevoutput in txjsonprev.vout:
    txrefundarray[] += {'address':txprevoutput.scriptPubKey.addresses[0], 'amount':txprevout.value} // 0th address only doesn't support multi-sig
Taylor Gerring
  • 413
  • 2
  • 9

3 Answers3

2

Bitcoin transactions do not have a 'from' address, and certainly no guaranteed way of determining a refund address. Transactions consume and produce coins, and while it is in theory possible to use the addresses the input coins were previously sent to, this is no information you should rely on (nor is it guaranteed to be available, though some sites use this technique).

For received transactions, the reference client lists the address by which you've received coins - not the sender. The best advice for determining a refund address, is for asking it from the customer.

In case you need something more automatic, there is a payment protocol being developed that works on top of Bitcoin, and allows negotiating transactions between sender and receiver before broadcasting them on the network. It includes a feature to automatically send a refund address with each transaction.

Pieter Wuille
  • 105,497
  • 9
  • 194
  • 308
  • I'm looking to determine the inputs and associated addresses for a given transaction with bitcoind in an automated way. "Asking it from the customer" is well beyond the scope of my question. – Taylor Gerring Aug 28 '13 at 02:34
  • 1
    You asked for a way to determine the source address of a transaction, to do refunds. Bitcoin, at the protocol level, has neither source addresses or a reliable way to determine refund addresses. Until the payment protocol is commonly available, the only way to do that is by asking a customer. Yes, transactions have inputs, and the outputs consumed by them may have been assigned to identifiable addresses, and this can be determined as you state. It's not an answer to your question though. – Pieter Wuille Sep 02 '13 at 09:27
  • I appreciate your input, however, I'm not looking for a theoretical protocol-level discussion. Many sites use a refund-like system based on the "inputs" and this was the answer I was looking for. – Taylor Gerring Sep 02 '13 at 13:39
  • 1
    Ok, then the only correct answer is "it does not exist". Refund addresses do not exist currently, and using the prevout addresses for this needs assumptions about the receiver's software, hurts the scalability of the ecosystem and its privacy as a whole. There is no answer to your question. I know many sites don't follow this, but they are hurting the ability of the ecosystem to outgrow some assumptions that may generally hold today. – Pieter Wuille Sep 11 '13 at 05:11
  • I'm unwilling to accept the answer of "it does't exist" as an excuse for not building something. The devs seem disinterested in adding simple features like "spend from" to bitcoind, so people have to make assumptions and build it externally. – Taylor Gerring Sep 11 '13 at 12:32
  • 1
    It is being worked on, and it's called the payment protocol which will be present in the 0.9 release. The point is that it doesn't belong in the P2P protocol, but in a layer on top, which allows transactions to be negotiated between sender and receiver before being broadcasted on the network. The blockchain is a expensive global thing to maintain, and functions only marginally as a communication protocol. There is no reason for putting data that is private information between sender and receiver into it. – Pieter Wuille Sep 12 '13 at 01:19
  • @PieterWuille There should be no semantic difference between the two concepts of "refund address" and "transaction sent from". "transaction sent from" can be determined and therefore an automated refund can be made (normally). If a web wallet fails to route the payment, that is THEIR problem. A bitcoin address represents a hash of a public key used to prove ownership, if a web wallet violates the principle of ownership then they have failed to implement bitcoin properly. – user3338098 Mar 18 '19 at 22:18
  • 1
    @user3338098 Ignoring that being terrible practice for privacy, it doesn't even always work. For example, in a CoinJoin transaction, some of the inputs will come from one sender, and some will come from another. You can of course have an understanding with a sender that a refund can be made, but in general you should not assume that a receiver will accept a transaction as a payment without being given an address to send it to explicitly. – Pieter Wuille Mar 18 '19 at 22:21
  • @PieterWuille I understand that it doesn't work all the time (because of web-providers) and that it reduces privacy. Can we agree that the original bitcoin white paper states coins made from digital signatures, which provides strong control of ownership and that web-providers are probably violating this principle of ownership by reusing private-keys for different users. – user3338098 Mar 21 '19 at 18:43
  • 1
    @user3338098 Even if you assume that, how will you deal with the case where multiple owners jointly construct a single transaction (where different input may be associated with different users)? This is very much an encouraged practice. – Pieter Wuille Mar 22 '19 at 23:13
  • @PieterWuille If someone payed for a product (that warned about automated refunds to the inputs of the transaction) with a CoinJoin transaction, that customer has ** literally ** disclaimed any ownership rights to their refund payment, by their choice to use a CoinJoin transaction to make the payment. Either way such transactions can be detected (all inputs and outputs the same is fairly easy to detect), and automated refunds halted for manual processing (with a processing fee deducted from their refund obviously! Though I would prefer to call it an idiot interaction fee.) – user3338098 Jun 11 '21 at 23:49
1

Someone has written a python snippet that attempts to determine the "input addresses" of a particular transaction using the outputs of the previous transaction as a workable, but not 100% unreliable solution. This accomplished what I need.

Taylor Gerring
  • 413
  • 2
  • 9
0

You should be seeing the same thing, but it looks like your results from bitcoind don't tell the full story. Everything in the details section is an output of the transaction. (Notice how each item with a category of "send" has a corresponding "receive" item with the same amount negated -- duplicates!) This doesn't actually tell you anything about the inputs. This could be a bug in bitcoind, but more likely there's another way, perhaps an extra command line parameter that will expose the inputs to the transaction as well.

John Henry
  • 1,193
  • 9
  • 21
  • 1
    getrawtransaction will show you the blockchain transaction, rather than the effect on your wallet (it does require the txindex=1 setting, though). That still won't give you a refund address, though (see my answer). – Pieter Wuille Aug 28 '13 at 01:02