8

Given a transaction's inputs and outputs, I'd like to be able to extract the wallet address (or addresses) which sent the transaction, and also the address/addresses that will receive the transaction.

  • Which part / field of the input refers to the hash of the output?

  • And which part / field of the output refers to the address which will receive the output?

I'm using bitcoinj. I've tried looking at the scriptSig of inputs and scriptPubKey of the outputs, but it isn't making much sense to me.

E.g, for the genesis transaction: https://blockchain.info/tx/4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b?show_adv=true

The output's scriptPubKey is [04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f] CHECKSIG

But the receiver address is 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa

How can I extract that the receiver address is that from that scriptPubKey?

2 Answers 2

6
  • Which part / field of the input refers to the hash of the output?

The outpoint contains a txid (32 bytes) and vout (4 bytes), which specify the output you're spending.

This is not the sending address!

What you do (when you're not dealing with a coinbase transaction) is that you look up the transaction with the txid, and look at the transaction output that corresponds to vout. So, for example, if vout was 3, you would look at the fourth output of the corresponding transaction. If vout was 0, you would look at the first output. The address that can spend that output is the sending address of the original transaction.

The genesis transaction is a coinbase transaction, so the txid is all zeroes, and the vout is all ones.

  • And which part / field of the output refers to the address which will receive the output?

It depends on the format of the output, but here are the general rules:

  • If it's P2PK, like here, run HASH160 on the first element of the scriptPubKey, then encode it as an address.
  • If it's P2PKH, take the third element of the scriptPubKey, and encode the pubkeyhash as an address.
  • If it's P2SH take the second element of the scriptPubKey, and encode it as an address with Address.fromP2SHHash.

I go into more detail about possible kinds of addresses here: Which bitcoin script forms should be detected when tracking wallet balance?

How can I extract that the receiver address is that from that scriptPubKey?

Do this:

import org.bitcoinj.core.*;
import org.bitcoinj.params.MainNetParams;

import org.spongycastle.crypto.digests.RIPEMD160Digest;

import java.nio.file.Files;
import java.io.File;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Test {
    public static void main(String[] args) throws Exception {
        byte[] b;
        NetworkParameters np = MainNetParams.get();
        Context.propagate(new Context(np));
        b = Files.readAllBytes(new File("genesis.bin").toPath());
        Transaction tx1 = new Transaction(np, b);
        System.out.println(tx1);
        byte[] pk = tx1.getOutput(0).getScriptPubKey().getPubKey();
        System.out.println(bytesToHex(pk));
        System.out.println(bytesToHex(hash160(pk)));
        Address a = new Address(np, hash160(pk));
        System.out.println(a);
    }
    static byte[] hash160(byte[] in) {
        MessageDigest d1;
        try {
            d1 = MessageDigest.getInstance("SHA-256");
        } catch(NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        d1.update(in);
        byte[] digest = d1.digest();
        RIPEMD160Digest d2 = new RIPEMD160Digest();
        d2.update(digest, 0, 32);
        byte[] ret = new byte[20];
        d2.doFinal(ret, 0);
        return ret;
    }
    final protected static char[] hexArray = "0123456789abcdef".toCharArray();
    public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for ( int j = 0; j < bytes.length; j++ ) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }
}

(Note that I have a file in my current working directory named genesis.bin, which contains the raw bytes for the genesis transaction.)

And you get:

  4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
     == COINBASE TXN (scriptSig PUSHDATA(4)[ffff001d] PUSHDATA(1)[04] PUSHDATA(69)[5468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73])  (scriptPubKey PUSHDATA(65)[04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f] CHECKSIG)

04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f
62e907b15cbf27d5425399ebf6f0fb50ebb88f18
1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa

Which is the address we were trying to get.

9
  • Thanks, very helpful. How do I know if an output is P2PK, P2PKH, or P2SH? And, do these 3 formats cover all the possible formats that it can be in? Also, how would I know if its a mining fee without an address? Lastly, to get the txid of inputs with Bitcoinj, would I use the input.getParentTransaction method? Commented Dec 26, 2016 at 12:13
  • I saw your answer at bitcoin.stackexchange.com/questions/35456/… which answers my first question. Remaining questions: 1) I'm assuming that the sender address of multi-sig txns cannot be retrieved? 2) Do you happen to know the hashes of txns using P2PKH and P2SH so I can test my parsing of them? 3) How can I retrieve the txId and vout of inputs thru Bitcoinj?. If I get this working, I'll submit this as a PR to bitcoinj. Thanks. Commented Dec 26, 2016 at 16:00
  • 1
    Would it be better if I created a new question for each of these? Commented Dec 26, 2016 at 16:04
  • 1
    @ClickUpvote 1) That's possible. You might mean "which addresses owned this Bitcoin before" or "which addresses actually signed this." First can be answered by looking at prev scriptPubKey, second requires prev scriptPubKey and current scriptSig. 2) P2PKH/P2SH 3) tx.getInput(vin).getOutpoint() followed by getHash or getIndex. PR) Cool! It would be nice to see that in bitcoinj. PS) I would make separate questions. There's a 600 character limit on commen
    – Nick ODell
    Commented Dec 26, 2016 at 16:53
  • 1
    @ClickUpvote You should be able to request the webpage https://blockchain.info/tx/<txid here>?format=hex to get a hex encoded version. Other API's have something similar.
    – Nick ODell
    Commented Dec 27, 2016 at 1:48
4

The scriptPubKey contains the public key used to synthesize the public address. Here are two pedantic approaches, not using bitcoinj, applying bx commands to synthesize the public address of interest above.

% echo 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f | bx sha256 | bx ripemd160 | bx base58check-encode

1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa

% echo 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f | bx ec-to-address

1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.