<p>When an input redeems a P2PKH output (pay to an address starting with a 1), the format of the input script (the scriptSig) is: <code>[signature] [public key]</code>. Because public keys are included in both standard input scripts (redeeming P2PKH outputs) and output scripts (P2PK), the <code>Script.getPubKey()</code> method has been written to return the public key in either input scripts or output scripts, hence it can work for you here.</p>

<p>Public key hashes (addresses), however, are only included in standard output scripts. So the <code>Script.getPubKeyHash()</code> method assumes you're talking about an <strong>output</strong> script, so it won't work for you here.</p>

<p>An input script redeeming a P2SH (pay to address starting with a 3) output is not necessarily 5 chunks, but the address is the hash of the redeem script, and the redeem script is always the last chunk. (Specifically, the input script is: <code>[script sig for the redeem script (may be multiple chunks)] [redeem script]</code>.) So all you'll need to do is get the last chunk (which is also what you're doing for P2PKH) and hash it.</p>

<p>The one place you might run into trouble is if you're redeeming a P2SH output, and the input script is 2 chunks. (This could come up, for instance, if the redeem script is <code>[public key] OP_CHECKSIG</code> - then the sigScript would be in the form <code>[signature] [20-byte hash]</code>, indistinguishable from one redeeming a P2PKH output.) The way to check this would be to look at the previous transaction and check its output scripts (which would also give you the addresses you're looking for more easily).</p>

<p>But assuming that when you redeem P2SH outputs the input script is more than 2 chunks, something like this should work:</p>

<pre><code>public static Address getWalletAddressOfSender(final Transaction tx) {

    Address fromAddress = null;

    for (final TransactionInput ti : tx.getInputs()) {

        try {

            Script scriptSig = ti.getScriptSig();
            List&lt;ScriptChunk&gt; chunks = scriptSig.getChunks();

            byte[] pubKey = chunks.get(chunks.size() - 1).data;
            byte[] pubKeyHash = Utils.sha256hash160(pubKey);

            if (chunks.size() &gt; 2) { // assume P2SH
                fromAddress = Address.fromP2SHHash(MainNetParams.get(), pubKeyHash);
            } else if (chunks.size() == 2) { // assume P2PKH
                fromAddress = new Address(MainNetParams.get(), pubKeyHash);
            }
            return fromAddress;

        } catch (final ScriptException x) {
            System.out.println(x.getMessage());
        }
    }

    return null;
}
</code></pre>

<p>(Note I used the variable names <code>pubKey</code> and <code>pubKeyHash</code> here, but in the case of P2SH these will instead be a script and a script hash. This method could also cause problems if the output being referenced is a multisig, P2PK, or something non-standard.)</p>

<p>I also notice your method only returns the first sender address. If a transaction has inputs from multiple sources, it might be worth returning a list or a set of those sender addresses. Just a thought.</p>

<p>Hope this helps!</p>

CC BY-SA 4.0
2019-01-14T04:43:23.753Z
Awesome! It works for most cases, however i encountered some transactions from P2SH addresses that have only 1 chunk. So for it to work on these cases i changed the code to `if (chunks.size() > 2 || chunks.size() == 1) { // assume P2SH`. And now it works. Check this one for example [f8eb444bdc11b4d85dfe44fb6aa2eb20628a93d23fde84ec60835a25acb617fd](https://www.blockchain.com/btc/tx/f8eb444bdc11b4d85dfe44fb6aa2eb20628a93d23fde84ec60835a25acb617fd?show_adv=true)
Bruno
CC BY-SA 4.0
2019-01-14T05:02:49.233Z
Also, using the same transaction example above, how do i detect that `3AJyCVDv5Nb55tpCnMxYxsqc3cAYQXZWEP` is an input address (so the code won't consider it the "destination" address) ? (Please consider my "getWalletAddressOfReceiver" code from original question). The getWalletAddressOfSender method returns `3BMEtyRXqVGRujANXNEXyTZ3tY3kRqraQQ` as the sender's address, which is the correct one btw. But the "getWalletAddressOfReceiver" will return `3AJyCVDv5Nb55tpCnMxYxsqc3cAYQXZWEP`(incorrect) instead of `1BNY3BKk6AhWNq8iYrCuJxiNMtHHSGbg4o` (correct).
Bruno
CC BY-SA 4.0
2019-01-15T05:08:19.873Z
Really a P2SH input could have any number of inputs. You could check the formatting more rigorously, i.e. if you're spending a P2PKH output it should have two chunks: The first should be a signature, usually of size 71-73 (althought it technically could be smaller than 71 bytes), and the second chunk will be a public key: either 33 or 65 bytes. But ultimately, you can only tell for sure from outputs, not from inputs.

I'll add a bit to my answer about the receiver address.
Vecna
CC BY-SA 4.0
2019-01-15T05:26:18.670Z
I think your problem with getting the receiver address is that you're only looking at one address at a time. This transaction has 2 inputs and 2 outputs that pay to addresses, so it's not enough to just return the first address from each place. So if you walk through getting the sender address and it's the first one, `3BMEtyRXqVGRujANXNEXyTZ3tY3kRqraQQ` and then compare it to the first output address, `3AJyCVDv5Nb55tpCnMxYxsqc3cAYQXZWEP`, then the code will say, "These are different. Return this receiver address." I would suggest using sets for the addresses, instead of just assuming one.
Vecna
CC BY-SA 4.0
2019-01-15T05:30:12.037Z
You'll also probably run into trouble with that second output because it's an OP_RETURN, so I'd suggest putting in a check before you call `script.getToAddress`, e.g. `if (script.isSentToAddress() || script.isPayToScriptHash()) { Address receiverAddress = script.getToAddress(MainNetParams.get(), true); }`
Vecna
CC BY-SA 4.0
2019-01-12T20:48:45.343Z
2019-01-12T21:04:07.257Z
2019-01-12T21:04:07.257Z
Vecna
<p>I'm trying to "extract" sender's addresses from OP_RETURN Bitcoin transactions, but my code is not working properly.</p>

<blockquote>
  <p>getWalletAddressOfSender(final Transaction tx)</p>
</blockquote>

<pre><code>public static Address getWalletAddressOfSender(final Transaction tx) {

    Address fromAddress = null;

    for (final TransactionInput ti : tx.getInputs()) {

        try {

            Script scriptSig = ti.getScriptSig();
            List&lt;ScriptChunk&gt; chunks = scriptSig.getChunks();

            byte[] pubKey = scriptSig.getPubKey();
            fromAddress = new Address(MainNetParams.get(), Utils.sha256hash160(pubKey));// scriptSig.getFromAddress(MainNetParams.get());

            return fromAddress;

        } catch (final ScriptException x) {
            System.out.println(x.getMessage());
        }
    }

    return null;
}
</code></pre>

<p>When the TransactionInput is from a address starting with 3... (P2SH) the list 'scriptSig.getChunks()' will have 5 items and 'getPubKey()' will throw the exception 'Script not of right size, expecting 2 but got 5'.</p>

<blockquote>
  <p>scriptSig.getPubKey()</p>
</blockquote>

<pre><code>/**
 * Returns the public key in this script. If a script contains two constants and nothing else, it is assumed to
 * be a scriptSig (input) for a pay-to-address output and the second constant is returned (the first is the
 * signature). If a script contains a constant and an OP_CHECKSIG opcode, the constant is returned as it is
 * assumed to be a direct pay-to-key scriptPubKey (output) and the first constant is the public key.
 *
 * @throws ScriptException if the script is none of the named forms.
 */
public byte[] getPubKey() throws ScriptException {
    if (chunks.size() != 2) {
        throw new ScriptException("Script not of right size, expecting 2 but got " + chunks.size());
    }
    final ScriptChunk chunk0 = chunks.get(0);
    final byte[] chunk0data = chunk0.data;
    final ScriptChunk chunk1 = chunks.get(1);
    final byte[] chunk1data = chunk1.data;
    if (chunk0data != null &amp;&amp; chunk0data.length &gt; 2 &amp;&amp; chunk1data != null &amp;&amp; chunk1data.length &gt; 2) {
        // If we have two large constants assume the input to a pay-to-address output.
        return chunk1data;
    } else if (chunk1.equalsOpCode(OP_CHECKSIG) &amp;&amp; chunk0data != null &amp;&amp; chunk0data.length &gt; 2) {
        // A large constant followed by an OP_CHECKSIG is the key.
        return chunk0data;
    } else {
        throw new ScriptException("Script did not match expected form: " + this);
    }
}
</code></pre>

<p>So i changed the code to</p>

<pre><code>public static Address getWalletAddressOfSender(final Transaction tx) {

    Address fromAddress = null;

    for (final TransactionInput ti : tx.getInputs()) {

        try {
            Script scriptSig = ti.getScriptSig();
            List&lt;ScriptChunk&gt; chunks = scriptSig.getChunks();
            if(chunks.size() &gt; 2) {
                System.out.print("This is a 5 chunks transaction... ");
                byte[] pubKeyHash = scriptSig.getPubKeyHash();
                fromAddress = Address.fromP2SHHash(MainNetParams.get(), pubKeyHash);
            } else {
                byte[] pubKey = scriptSig.getPubKey();
                fromAddress = new Address(MainNetParams.get(), Utils.sha256hash160(pubKey));// scriptSig.getFromAddress(MainNetParams.get());   
            }

            return fromAddress;
        } catch (final ScriptException x) {
            System.out.println(x.getMessage());
        }
    }

    return null;
}
</code></pre>

<p>but it will also throw another exception 'Script not in the standard scriptPubKey form' (when chunks.size() > 2)</p>

<blockquote>
  <p>scriptSig.getPubKeyHash()</p>
</blockquote>

<pre><code>/**
 * &lt;p&gt;If a program matches the standard template DUP HASH160 &amp;lt;pubkey hash&amp;gt; EQUALVERIFY CHECKSIG
 * then this function retrieves the third element.
 * In this case, this is useful for fetching the destination address of a transaction.&lt;/p&gt;
 * 
 * &lt;p&gt;If a program matches the standard template HASH160 &amp;lt;script hash&amp;gt; EQUAL
 * then this function retrieves the second element.
 * In this case, this is useful for fetching the hash of the redeem script of a transaction.&lt;/p&gt;
 * 
 * &lt;p&gt;Otherwise it throws a ScriptException.&lt;/p&gt;
 *
 */
public byte[] getPubKeyHash() throws ScriptException {
    if (isSentToAddress())
        return chunks.get(2).data;
    else if (isPayToScriptHash())
        return chunks.get(1).data;
    else
        throw new ScriptException("Script not in the standard scriptPubKey form");
}
</code></pre>

<blockquote>
  <p>Here's a transaction where chunks.size() == 2 and i'm able to extract
  sender's address (1KYiKJEfdJtap9QX2v9BXJMpz2SfU4pgZw)</p>
</blockquote>

<p><a href="https://www.blockchain.com/btc/tx/b5765d54e275794939eb48c77dd8862a6e865dee6d71bc7004660dca32de8c43" rel="nofollow noreferrer">https://www.blockchain.com/btc/tx/b5765d54e275794939eb48c77dd8862a6e865dee6d71bc7004660dca32de8c43</a></p>

<blockquote>
  <p>These are some transactions where chunks.size() == 5 and i'm NOT able to
  extract the sender's address (3....)</p>
</blockquote>

<p><a href="https://www.blockchain.com/btc/tx/b02e17479660a4685daba4e8f0f73aea96e0c36ab14142b68f868ac76a77455a" rel="nofollow noreferrer">https://www.blockchain.com/btc/tx/b02e17479660a4685daba4e8f0f73aea96e0c36ab14142b68f868ac76a77455a</a></p>

<p><a href="https://www.blockchain.com/btc/tx/f0a6708167eca88b9fe4dad4c110ddff2b3f6c5e08771793b8ca40400d4effab" rel="nofollow noreferrer">https://www.blockchain.com/btc/tx/f0a6708167eca88b9fe4dad4c110ddff2b3f6c5e08771793b8ca40400d4effab</a></p>

<p><a href="https://www.blockchain.com/btc/tx/28a91393393916367e890965200d4f8af04416b65ee6fea22c0adf29af8ea3b8" rel="nofollow noreferrer">https://www.blockchain.com/btc/tx/28a91393393916367e890965200d4f8af04416b65ee6fea22c0adf29af8ea3b8</a></p>

<p>What's the correct way of getting the sender's address in these cases ?</p>

<p>FYI: here's my shitty method to get the recipient's address</p>

<pre><code>// THIS IF A FUCKED UP WORKAROUND, FIX ASAP
@Nullable
public static Address getWalletAddressOfReceiver(final Transaction tx, final Address senderAddress) {

    for (final TransactionOutput output : tx.getOutputs()) {
        try {
            final Script script = output.getScriptPubKey();     
            Address receiverAddress = script.getToAddress(MainNetParams.get(), true);
            if(receiverAddress.equals(senderAddress))
                continue;
            return receiverAddress;

        } catch (final ScriptException x) {

        }
    }

    return null;
}
</code></pre>

<p>As the recipient's address is in a random position in "tx.getOutputs()" i just skip it if it's equal to sender's address and get the next one.</p>

<bitcoinj><p2sh><transaction-input><input-script><p2pk>
bitcoinj java library not decoding input addresses for some transactions
Bruno
# bitcoinj java library not decoding input addresses for some transactions

(Asked by: username_0 on 2019-01-08)

I'm trying to "extract" sender's addresses from OP\_RETURN Bitcoin transactions, but my code is not working properly.

> getWalletAddressOfSender(final Transaction tx)

```
public static Address getWalletAddressOfSender(final Transaction tx) {

    Address fromAddress = null;

    for (final TransactionInput ti : tx.getInputs()) {

        try {

            Script scriptSig = ti.getScriptSig();
            List<ScriptChunk> chunks = scriptSig.getChunks();

            byte[] pubKey = scriptSig.getPubKey();
            fromAddress = new Address(MainNetParams.get(), Utils.sha256hash160(pubKey));// scriptSig.getFromAddress(MainNetParams.get());

            return fromAddress;

        } catch (final ScriptException x) {
            System.out.println(x.getMessage());
        }
    }

    return null;
}

```

When the TransactionInput is from a address starting with 3... (P2SH) the list 'scriptSig.getChunks()' will have 5 items and 'getPubKey()' will throw the exception 'Script not of right size, expecting 2 but got 5'.

> scriptSig.getPubKey()

```
/**
 * Returns the public key in this script. If a script contains two constants and nothing else, it is assumed to
 * be a scriptSig (input) for a pay-to-address output and the second constant is returned (the first is the
 * signature). If a script contains a constant and an OP_CHECKSIG opcode, the constant is returned as it is
 * assumed to be a direct pay-to-key scriptPubKey (output) and the first constant is the public key.
 *
 * @throws ScriptException if the script is none of the named forms.
 */
public byte[] getPubKey() throws ScriptException {
    if (chunks.size() != 2) {
        throw new ScriptException("Script not of right size, expecting 2 but got " + chunks.size());
    }
    final ScriptChunk chunk0 = chunks.get(0);
    final byte[] chunk0data = chunk0.data;
    final ScriptChunk chunk1 = chunks.get(1);
    final byte[] chunk1data = chunk1.data;
    if (chunk0data != null && chunk0data.length > 2 && chunk1data != null && chunk1data.length > 2) {
        // If we have two large constants assume the input to a pay-to-address output.
        return chunk1data;
    } else if (chunk1.equalsOpCode(OP_CHECKSIG) && chunk0data != null && chunk0data.length > 2) {
        // A large constant followed by an OP_CHECKSIG is the key.
        return chunk0data;
    } else {
        throw new ScriptException("Script did not match expected form: " + this);
    }
}

```

So i changed the code to

```
public static Address getWalletAddressOfSender(final Transaction tx) {

    Address fromAddress = null;

    for (final TransactionInput ti : tx.getInputs()) {

        try {
            Script scriptSig = ti.getScriptSig();
            List<ScriptChunk> chunks = scriptSig.getChunks();
            if(chunks.size() > 2) {
                System.out.print("This is a 5 chunks transaction... ");
                byte[] pubKeyHash = scriptSig.getPubKeyHash();
                fromAddress = Address.fromP2SHHash(MainNetParams.get(), pubKeyHash);
            } else {
                byte[] pubKey = scriptSig.getPubKey();
                fromAddress = new Address(MainNetParams.get(), Utils.sha256hash160(pubKey));// scriptSig.getFromAddress(MainNetParams.get());   
            }

            return fromAddress;
        } catch (final ScriptException x) {
            System.out.println(x.getMessage());
        }
    }

    return null;
}

```

but it will also throw another exception 'Script not in the standard scriptPubKey form' (when chunks.size() > 2)

> scriptSig.getPubKeyHash()

```
/**
 * <p>If a program matches the standard template DUP HASH160 &lt;pubkey hash&gt; EQUALVERIFY CHECKSIG
 * then this function retrieves the third element.
 * In this case, this is useful for fetching the destination address of a transaction.</p>
 * 
 * <p>If a program matches the standard template HASH160 &lt;script hash&gt; EQUAL
 * then this function retrieves the second element.
 * In this case, this is useful for fetching the hash of the redeem script of a transaction.</p>
 * 
 * <p>Otherwise it throws a ScriptException.</p>
 *
 */
public byte[] getPubKeyHash() throws ScriptException {
    if (isSentToAddress())
        return chunks.get(2).data;
    else if (isPayToScriptHash())
        return chunks.get(1).data;
    else
        throw new ScriptException("Script not in the standard scriptPubKey form");
}

```

> Here's a transaction where chunks.size() == 2 and i'm able to extract
> sender's address (1KYiKJEfdJtap9QX2v9BXJMpz2SfU4pgZw)

<https://www.blockchain.com/btc/tx/b5765d54e275794939eb48c77dd8862a6e865dee6d71bc7004660dca32de8c43>

> These are some transactions where chunks.size() == 5 and i'm NOT able to
> extract the sender's address (3....)

<https://www.blockchain.com/btc/tx/b02e17479660a4685daba4e8f0f73aea96e0c36ab14142b68f868ac76a77455a>

<https://www.blockchain.com/btc/tx/f0a6708167eca88b9fe4dad4c110ddff2b3f6c5e08771793b8ca40400d4effab>

<https://www.blockchain.com/btc/tx/28a91393393916367e890965200d4f8af04416b65ee6fea22c0adf29af8ea3b8>

What's the correct way of getting the sender's address in these cases ?

FYI: here's my shitty method to get the recipient's address

```
// THIS IF A FUCKED UP WORKAROUND, FIX ASAP
@Nullable
public static Address getWalletAddressOfReceiver(final Transaction tx, final Address senderAddress) {

    for (final TransactionOutput output : tx.getOutputs()) {
        try {
            final Script script = output.getScriptPubKey();     
            Address receiverAddress = script.getToAddress(MainNetParams.get(), true);
            if(receiverAddress.equals(senderAddress))
                continue;
            return receiverAddress;

        } catch (final ScriptException x) {

        }
    }

    return null;
}

```

As the recipient's address is in a random position in "tx.getOutputs()" i just skip it if it's equal to sender's address and get the next one.

**Tags:** bitcoinj, p2sh, transaction-input, input-script, p2pk


---

## 1 answers

### Answer by username_1 on 2019-01-12. Score: 2 | Accepted answer

When an input redeems a P2PKH output (pay to an address starting with a 1), the format of the input script (the scriptSig) is: `[signature] [public key]`. Because public keys are included in both standard input scripts (redeeming P2PKH outputs) and output scripts (P2PK), the `Script.getPubKey()` method has been written to return the public key in either input scripts or output scripts, hence it can work for you here.

Public key hashes (addresses), however, are only included in standard output scripts. So the `Script.getPubKeyHash()` method assumes you're talking about an **output** script, so it won't work for you here.

An input script redeeming a P2SH (pay to address starting with a 3) output is not necessarily 5 chunks, but the address is the hash of the redeem script, and the redeem script is always the last chunk. (Specifically, the input script is: `[script sig for the redeem script (may be multiple chunks)] [redeem script]`.) So all you'll need to do is get the last chunk (which is also what you're doing for P2PKH) and hash it.

The one place you might run into trouble is if you're redeeming a P2SH output, and the input script is 2 chunks. (This could come up, for instance, if the redeem script is `[public key] OP_CHECKSIG` - then the sigScript would be in the form `[signature] [20-byte hash]`, indistinguishable from one redeeming a P2PKH output.) The way to check this would be to look at the previous transaction and check its output scripts (which would also give you the addresses you're looking for more easily).

But assuming that when you redeem P2SH outputs the input script is more than 2 chunks, something like this should work:

```
public static Address getWalletAddressOfSender(final Transaction tx) {

    Address fromAddress = null;

    for (final TransactionInput ti : tx.getInputs()) {

        try {

            Script scriptSig = ti.getScriptSig();
            List<ScriptChunk> chunks = scriptSig.getChunks();

            byte[] pubKey = chunks.get(chunks.size() - 1).data;
            byte[] pubKeyHash = Utils.sha256hash160(pubKey);

            if (chunks.size() > 2) { // assume P2SH
                fromAddress = Address.fromP2SHHash(MainNetParams.get(), pubKeyHash);
            } else if (chunks.size() == 2) { // assume P2PKH
                fromAddress = new Address(MainNetParams.get(), pubKeyHash);
            }
            return fromAddress;

        } catch (final ScriptException x) {
            System.out.println(x.getMessage());
        }
    }

    return null;
}

```

(Note I used the variable names `pubKey` and `pubKeyHash` here, but in the case of P2SH these will instead be a script and a script hash. This method could also cause problems if the output being referenced is a multisig, P2PK, or something non-standard.)

I also notice your method only returns the first sender address. If a transaction has inputs from multiple sources, it might be worth returning a list or a set of those sender addresses. Just a thought.

Hope this helps!

> **Comments:**
> **username_0**: Awesome! It works for most cases, however i encountered some transactions from P2SH addresses that have only 1 chunk. So for it to work on these cases i changed the code to `if (chunks.size() > 2 || chunks.size() == 1) { // assume P2SH`. And now it works. Check this one for example [f8eb444bdc11b4d85dfe44fb6aa2eb20628a93d23fde84ec60835a25acb617fd](https://www.blockchain.com/btc/tx/f8eb444bdc11b4d85dfe44fb6aa2eb20628a93d23fde84ec60835a25acb617fd?show_adv=true)  
> **username_0**: Also, using the same transaction example above, how do i detect that `3AJyCVDv5Nb55tpCnMxYxsqc3cAYQXZWEP` is an input address (so the code won't consider it the "destination" address) ? (Please consider my "getWalletAddressOfReceiver" code from original question). The getWalletAddressOfSender method returns `3BMEtyRXqVGRujANXNEXyTZ3tY3kRqraQQ` as the sender's address, which is the correct one btw. But the "getWalletAddressOfReceiver" will return `3AJyCVDv5Nb55tpCnMxYxsqc3cAYQXZWEP`(incorrect) instead of `1BNY3BKk6AhWNq8iYrCuJxiNMtHHSGbg4o` (correct).  
> **username_1**: Really a P2SH input could have any number of inputs. You could check the formatting more rigorously, i.e. if you're spending a P2PKH output it should have two chunks: The first should be a signature, usually of size 71-73 (althought it technically could be smaller than 71 bytes), and the second chunk will be a public key: either 33 or 65 bytes. But ultimately, you can only tell for sure from outputs, not from inputs.  I'll add a bit to my answer about the receiver address.  
> **username_1**: I think your problem with getting the receiver address is that you're only looking at one address at a time. This transaction has 2 inputs and 2 outputs that pay to addresses, so it's not enough to just return the first address from each place. So if you walk through getting the sender address and it's the first one, `3BMEtyRXqVGRujANXNEXyTZ3tY3kRqraQQ` and then compare it to the first output address, `3AJyCVDv5Nb55tpCnMxYxsqc3cAYQXZWEP`, then the code will say, "These are different. Return this receiver address." I would suggest using sets for the addresses, instead of just assuming one.  
> **username_1**: You'll also probably run into trouble with that second output because it's an OP_RETURN, so I'd suggest putting in a check before you call `script.getToAddress`, e.g. `if (script.isSentToAddress() || script.isPayToScriptHash()) { Address receiverAddress = script.getToAddress(MainNetParams.get(), true); }`  

---

