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?

Click Upvote
  • 183
  • 1
  • 6

2 Answers2

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.

Nick ODell
  • 29,184
  • 11
  • 69
  • 129
  • 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? – Click Upvote Dec 26 '16 at 12:13
  • I saw your answer at http://bitcoin.stackexchange.com/questions/35456/which-bitcoin-script-forms-should-be-detected-when-tracking-wallet-balance/35458 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. – Click Upvote Dec 26 '16 at 16:00
  • 1
    Would it be better if I created a new question for each of these? – Click Upvote Dec 26 '16 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](https://blockchain.info/tx/08a1bd2a976d7ab487806e6540b43cc5135c3e5e0043e613446b8af29fa25e17) 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 Dec 26 '16 at 16:53
  • Does `input.getOutput.getHash` refer to the txn id and `getIndex` refer to the vout of the output of that txn? P.S thanks a bunch, I've been trying for a few days to get answers to these qs, you're the first person who has been able to answer them. :) – Click Upvote Dec 26 '16 at 17:16
  • Is it possible to download the binary data of those txns from blockchain.info or another method, without having to traverse the chain looking for it? – Click Upvote Dec 26 '16 at 23:59
  • 1
    @ClickUpvote You should be able to request the webpage `https://blockchain.info/tx/?format=hex` to get a hex encoded version. Other API's have something similar. – Nick ODell Dec 27 '16 at 01:48
  • So e.g, https://blockchain.info/tx/1bc137186cba1c1e36aaa805bee2b964d827c53cc3b05883e14f820e7cee3083?format=hex , that can be saved as a .bin file and passed on to Transaction as in your example code? Or does anything further need to be done to the hex data? – Click Upvote Dec 27 '16 at 10:29
  • @ClickUpvote It's got to be converted from hex to raw bytes. http://stackoverflow.com/questions/8890174/in-java-how-do-i-convert-a-hex-string-to-a-byte – Nick ODell Dec 27 '16 at 16:50
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

skaht
  • 3,017
  • 1
  • 12
  • 23