Most of the output addresses follow one of the following 'standard outputs':
Legacy Outputs
P2PK: scriptPubKey: <public_key> OP_CHECKSIG
. Output pays the public key directly and hence does not have a direct address.
P2PKH: scriptPubKey: OP_DUP OP_HASH160 <hash160 of pubkey> OP_EQUALVERIFY OP_CHECKSIG
. For this kind of output you just need to base58check the hash160 of pubkey
with version 0x00
and you will get the addresses that starts with 1.
P2SH: scriptPubKey: OP_HASH160 <redeem_script> OP_EQUAL
. You again need to just base58check the redeem_script
with version 0x05
and you will get an address starting with 3.
Multisig: scriptPubKey: M <public_key1>...<public_keyN> N OP_CHECKMULTISIG
. In this case, you cannot get the addresses as the output pays the public keys directly.
Segwit Outputs
- P2WPKH:
scriptPubKey: <0x00 (version)> <hash160 of pubkey>
. You will need to create a bech32 address using the version and 20-byte redeem script and you will get an address starting with bc1. You can find the python script for bech32 encoding here.
- P2SH:
scriptPubKey <version: 0x00> <sha256 of redeem_script>
. Again a bech32 address starting bc1 but the redeem_script is 32 bytes rather than 20 bytes for P2WPKH.
- P2SH(P2WPKH):
scriptPubKey: OP_HASH160 <redeem_script > OP_EQUAL
. The encoding is same as legacy P2SH. Base58check with 0x05
version. For a more detailed overview on how the 'redeem_script` and addresses are generated for P2SH(P2WPKH) see my other answer here.
OP_RETURN
Many times people like to encode some data in the Bitcoin blockchain. For that, you use a OP_RETURN opcode. The scriptPubKey:<OP_RETURN><OP_PUSHDATA1><bytes to push><script>
.