<p>You are not considering the op codes in the pub_key string.
For example, a script_pub_key could be OP_DUP OP_HASH160 [pub_key] ...
and you have to pull out the pub_key.<br>
This sample code shows the addresses, you can check them against a block explorer for the same transaction id.  Note that the byte after OP_HASH160 gives the length of the pub_key in bytes after it, so it needs to be skipped as well to generate the address.</p>

<p><pre><code>
import sys
import base58
import hashlib
import binascii
from blockchain.reader import BlockchainFileReader
block_reader=BlockchainFileReader('/var/data/bitcoin-data/blocks/blk00325.dat')
satochi_convert=1e8
def sha256(x):
    h=hashlib.new('sha256')
    h.update(x)
    return h.digest()</p>

<p>def hashStr(buffer):
    return binascii.hexlify(buffer)</p>

<p>for block in block_reader:
    #block has .header, .transactions
    for iter,tx in enumerate(block.transactions):
        print('  Transaction (txn_hash):{} {}'.format(type(tx.txn_hash),tx.txn_hash))
        for x in tx.outputs:
            script_pub_key_str=hashStr(x.script_pub_key)
            if script_pub_key_str[0:4]==b'76a9':
                #This is a pubkeyhash
                bytes=x.script_pub_key[2]  #number of bytes in the pub_key
                assert bytes==20
                public_key = x.script_pub_key[3:3+bytes] #20 bytes
                z=b'\00'+public_key
                #checksum=sha256(sha256(z))[:4]
                #address1=base58.b58encode(z + checksum)
                address2=base58.b58encode_check(z)   # adds checksum for you
                print('  output value {:&lt;20} address {}'.format(float(x.value)/satochi_convert,address2))
            elif script_pub_key_str[0:2]==b'a9':
                #this is a scripthash (pay-to-script address)
                bytes=x.script_pub_key[1]  #number of bytes in the pub_key
                assert bytes==20
                public_key = x.script_pub_key[2:2+bytes] #20 bytes
                z=b'\05'+public_key  #used for mainnet
                address2=base58.b58encode_check(z)
                print('  output value {:&lt;20} address {}'.format(float(x.value)/satochi_convert,address2))
            else:
                print('  output value {:&lt;20} other {}'.format(float(x.value)/satochi_convert,script_pub_key_str))
        print()</p>

<p></pre></code>
Sample output for first transaction in your block file is:
<pre><code>
 Transaction (txn_hash): cc728403552d5e1fddf06e6a7e8552353f315be6c1a43a8e64e4d11b081d4ca3
  output value 25.17686501          address 1N6LrEDiHuFwSyJYj2GedZM2FGk7kkLjn
  output value 0.22864963           address 1Hr9uwzwXWpjQDNUWdZ1i9qnoSpnniJe4U
....
</pre></code></p>

<p>OP codes here: <a href="https://en.bitcoin.it/wiki/Script" rel="nofollow noreferrer">https://en.bitcoin.it/wiki/Script</a>, 
scriptpubkey info: <a href="https://en.bitcoin.it/wiki/Transaction" rel="nofollow noreferrer">https://en.bitcoin.it/wiki/Transaction</a>
NOTE: this is just an example of how to calculate addresses, it is not very robust as it does not check other OP codes afterwards, other possible payment scripts, etc.</p>

CC BY-SA 3.0
2017-12-18T21:56:53.547Z
2017-12-18T21:56:53.547Z
dan grunberg
<p>I am currently trying myself in parsing the blockchain using <a href="https://github.com/toidi/pyblockchain" rel="nofollow noreferrer">pyblockchain</a>. My problem is that I am not able to encode the <code>scriptPubKey</code> correctly - although I don't know what I could possibly do wrong.</p>

<p>Below you can see how I traverse the blockchain:</p>

<pre><code>from blockchain.reader import BlockchainFileReader

import hashlib
import base58

block_reader = BlockchainFileReader('/media/Data/btc/blocks/blk00325.dat')

count = 0

for block in block_reader:    
    count +=1        
    for t in block.transactions:
        for outp in t.outputs:
            addr = base58.b58encode(outp.script_pub_key)
            if addr.startswith('1'):
                print(addr)        
    if count &gt;= 5:
        break
</code></pre>

<p>If I, in my Jupyter notebook, take a look at <code>outp</code>, I'll find for</p>

<pre><code>outp.script_pub_key
&gt;&gt; b'v\xa9\x14\x1e\xbev\x83\xceJd\xad\xc9\x17\xe9\xb1\x93\x7f\x12&amp;Q\xcb\xab\xa1\x88\xac'
</code></pre>

<p>this:</p>

<pre><code>base58.b58encode(outp.script_pub_key)
&gt;&gt; 'pkJBVCg6k54E7ZiP7cvxbCvtN9aY9zEcgK'
</code></pre>

<p>and this is not a <a href="http://lenschulwitz.com/base58" rel="nofollow noreferrer">valid bitcoin address</a>.</p>

<p>Apparently, bitcoin addresses are supposed to be encoded i <a href="https://en.bitcoin.it/wiki/Base58Check_encoding" rel="nofollow noreferrer">Base58Check</a> - however, that does not work either:</p>

<pre><code>base58.b58encode_check(outp.script_pub_key)
&gt;&gt; '6PSJQapdQn8VeG9SBuZdH8q2ysyP4ND6dmspzLZb'
</code></pre>

<p>So what am I doing wrong here?</p>

<address>
How to convert scriptPubKey bytes to Bitcoin address?
Stefan Falk
# How to convert scriptPubKey bytes to Bitcoin address?

(Asked by: username_0 on 2017-12-08)

I am currently trying myself in parsing the blockchain using [pyblockchain](https://github.com/toidi/pyblockchain). My problem is that I am not able to encode the `scriptPubKey` correctly - although I don't know what I could possibly do wrong.

Below you can see how I traverse the blockchain:

```
from blockchain.reader import BlockchainFileReader

import hashlib
import base58

block_reader = BlockchainFileReader('/media/Data/btc/blocks/blk00325.dat')

count = 0

for block in block_reader:    
    count +=1        
    for t in block.transactions:
        for outp in t.outputs:
            addr = base58.b58encode(outp.script_pub_key)
            if addr.startswith('1'):
                print(addr)        
    if count >= 5:
        break

```

If I, in my Jupyter notebook, take a look at `outp`, I'll find for

```
outp.script_pub_key
>> b'v\xa9\x14\x1e\xbev\x83\xceJd\xad\xc9\x17\xe9\xb1\x93\x7f\x12&Q\xcb\xab\xa1\x88\xac'

```

this:

```
base58.b58encode(outp.script_pub_key)
>> 'pkJBVCg6k54E7ZiP7cvxbCvtN9aY9zEcgK'

```

and this is not a [valid bitcoin address](http://lenschulwitz.com/base58).

Apparently, bitcoin addresses are supposed to be encoded i [Base58Check](https://en.bitcoin.it/wiki/Base58Check_encoding) - however, that does not work either:

```
base58.b58encode_check(outp.script_pub_key)
>> '6PSJQapdQn8VeG9SBuZdH8q2ysyP4ND6dmspzLZb'

```

So what am I doing wrong here?

**Tags:** address


---

## 1 answers

### Answer by username_1 on 2017-12-18. Score: 3

You are not considering the op codes in the pub\_key string.
For example, a script\_pub\_key could be OP\_DUP OP\_HASH160 [pub\_key] ...
and you have to pull out the pub\_key.  
This sample code shows the addresses, you can check them against a block explorer for the same transaction id. Note that the byte after OP\_HASH160 gives the length of the pub\_key in bytes after it, so it needs to be skipped as well to generate the address.

```

import sys
import base58
import hashlib
import binascii
from blockchain.reader import BlockchainFileReader
block_reader=BlockchainFileReader('/var/data/bitcoin-data/blocks/blk00325.dat')
satochi_convert=1e8
def sha256(x):
    h=hashlib.new('sha256')
    h.update(x)
    return h.digest()

def hashStr(buffer):
    return binascii.hexlify(buffer)

for block in block_reader:
    #block has .header, .transactions
    for iter,tx in enumerate(block.transactions):
        print('  Transaction (txn_hash):{} {}'.format(type(tx.txn_hash),tx.txn_hash))
        for x in tx.outputs:
            script_pub_key_str=hashStr(x.script_pub_key)
            if script_pub_key_str[0:4]==b'76a9':
                #This is a pubkeyhash
                bytes=x.script_pub_key[2]  #number of bytes in the pub_key
                assert bytes==20
                public_key = x.script_pub_key[3:3+bytes] #20 bytes
                z=b'\00'+public_key
                #checksum=sha256(sha256(z))[:4]
                #address1=base58.b58encode(z + checksum)
                address2=base58.b58encode_check(z)   # adds checksum for you
                print('  output value {:<20} address {}'.format(float(x.value)/satochi_convert,address2))
            elif script_pub_key_str[0:2]==b'a9':
                #this is a scripthash (pay-to-script address)
                bytes=x.script_pub_key[1]  #number of bytes in the pub_key
                assert bytes==20
                public_key = x.script_pub_key[2:2+bytes] #20 bytes
                z=b'\05'+public_key  #used for mainnet
                address2=base58.b58encode_check(z)
                print('  output value {:<20} address {}'.format(float(x.value)/satochi_convert,address2))
            else:
                print('  output value {:<20} other {}'.format(float(x.value)/satochi_convert,script_pub_key_str))
        print()

```

Sample output for first transaction in your block file is:

```

 Transaction (txn_hash): cc728403552d5e1fddf06e6a7e8552353f315be6c1a43a8e64e4d11b081d4ca3
  output value 25.17686501          address 1N6LrEDiHuFwSyJYj2GedZM2FGk7kkLjn
  output value 0.22864963           address 1Hr9uwzwXWpjQDNUWdZ1i9qnoSpnniJe4U
....

```

OP codes here: <https://en.bitcoin.it/wiki/Script>,
scriptpubkey info: <https://en.bitcoin.it/wiki/Transaction>
NOTE: this is just an example of how to calculate addresses, it is not very robust as it does not check other OP codes afterwards, other possible payment scripts, etc.


---

