2

I am creating a block parser and just learned about Scripts in Bitcoin yesterday which is kind of confusing so far. I want to extract the addresses involved in each transaction. Right now, I am able to read the script for each output. To extract the address, am I correct in thinking that my code will need to handle all of the different formats of scriptPubKeys? Is there any sample code out there to guide me? If I am completely wrong, how should I do it?

2 Answers 2

3

Yes, to get addresses from scriptPubKeys, you will need to do a pattern match. There are only a small number of address types each with their own fixed scriptPubKey pattern. Keep in mind that not all scriptPubKeys map to an address so you will find scriptPubKeys that have no address and you will need to handle those.

Bitcoin Core has a pattern matcher for going from scriptPubKeys to address types in the solver function. The MatchPayToPubkey, MatchPayToPubkeyHash, and MatchMultisig can be found higher up in that file. The IsPayToScriptHash and IsWitnessProgram functions can be found here.

One thing to note about the solver is that it does not return just address types. Some of the types it returns do not map to addresses. These are TX_NULLDATA, TX_MULTISIG, TX_PUBKEY, and TX_NONSTANDARD.

It may also be useful for you to see how you get the scriptPubKey from an address. Bitcoin Core does it here.

5
  • Thanks a lot Andrew. I'm not great at C++ (only been programming for a year) but I think I can use it as a guide. One more question: why would a scriptPubKey not map to an address? For the purposes of my block parser, would I just discard it?
    – fon
    Commented Jul 13, 2019 at 5:56
  • A scriptPubKey can be literally any sequence of bytes; it doesn't have to be a valid script, the output will just be unspendable. Those standard scriptPubKeys that don't have addresses occur because there was/is no reason for them to have addresses. A very common one that you will see are Pay to Pubkey outputs. These are in basically all of the early blocks because the original Bitcoin client created coinbase transactions with P2PK outputs. Some block explorers will convert these to addresses, but that is incorrect.
    – Ava Chow
    Commented Jul 13, 2019 at 6:02
  • I recommend that you do not discard them because you will be losing information. It is useful to know exactly what the scriptPubKey for an output is. So you should still just store them. Maybe decode them into opcode notation instead of storing the bytes themselves, but you should still keep the scripts around in some form.
    – Ava Chow
    Commented Jul 13, 2019 at 6:03
  • Regarding the handling of segwit txns, is my understanding correct? 1) Check if it's non-native or native. 2) If the former, check if it's p2sh-p2wpkh or p2sh-p2wsh and then handle it like any other p2sh. 3) If the latter, determine if it's p2wpkh or p2wsh. 4) After extracting the script hash, perform the appropriate hashing and base58check encoding to extract the addresses?
    – fon
    Commented Jul 15, 2019 at 6:56
  • You won't be able to tell if an output is non-native segwit. The scriptPubKey will not contain the segwit script at all, you will just see a p2sh output. So you should treat all p2sh outputs the same, because, as outputs, they are.
    – Ava Chow
    Commented Jul 15, 2019 at 13:38
0

With library https://github.com/petertodd/python-bitcoinlib

a P2WPKH address derivation example:

from bitcoin import SelectParams
from bitcoin.core import x
from bitcoin.core.script import CScript
from bitcoin.wallet import P2WPKHBitcoinAddress

SelectParams('mainnet')
# Create an address from that private key.
scriptPubKey = CScript(x('Paste_scriptPubKey_Here'))
address = P2WPKHBitcoinAddress.from_scriptPubKey(scriptPubKey)
print(address)

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.