10

can someone walk me through the process of combining script inputs and outputs to reveal the base58 encoded input and output addresses. take for example, block 728. this has two raw script inputs:

493046022100e26d9ff76a07d68369e5782be3f8532d25ecc8add58ee256da6c550b52e8006b022100b4431f5a9a4dcb51cbdcaae935218c0ae4cfc8aa903fe4e5bac4c208290b7d5d01

and

493046022100a2ab7cdc5b67aca032899ea1b262f6e8181060f5a34ee667a82dac9c7b7db4c3022100911bc945c4b435df8227466433e56899fbb65833e4853683ecaa12ee840d16bf01

the first byte of each (49 hex = 73 dec) is the instruction to push 73 bytes onto the stack. according to the wiki each of these input scripts consists of a signature and a public key.

the raw output script is

76a91412ab8dc588ca9d5787dde7eb29569da63c3a238c88ac

which translates to the instructions

OP_DUP OP_HASH160 OP_PUSHDATA0(20 bytes) 12ab8dc588ca9d5787dde7eb29569da63c3a238c OP_EQUALVERIFY OP_CHECKSIG

so given this information, how can i extract input addresses (as shown in blockexplorer.com)? is this even possible?

1Miuw7ifaTYY5qrzKYFcTDiojSFxRfAqwP and 18KrJNtPVu6LWRNPQReqF29iFm7vDhirMk

and output address

12higDjoCCNXSA95xZMWUdPvXNmkAduhWv
0

3 Answers 3

12

the output address is derived solely from the output script starting from step 4 in the wiki like so:

first add leading zeros:

0012ab8dc588ca9d5787dde7eb29569da63c3a238c

then hash with sha256 (if you look in the wiki this is actually part of the OP_HASH160 operation) to give:

e158c4be10913422dadcf1c36843020ebb3ffe9d0cb13fb9e8c0a564a53c7832

then hashed with sha256 again (the wiki is wrong here - it says to use ripemd160, but actually sha256 is required again) to give:

96bf1d277213bbcd91145138e4c7ad8dcd6e1de1c39884fcbc1f5a6d4d7aee93

then grab the first 4 bytes of this result (96bf1d27) and stick them on the end of the original hash160 public key with leading zeros:

0012ab8dc588ca9d5787dde7eb29569da63c3a238c96bf1d27

convert to decimal:

457790304922245030616719694560989441716273193824169172263

base58 encode to give:

2higDjoCCNXSA95xZMWUdPvXNmkAduhWv

and stick a 1 in front of it all to get the bitcoin output address:

12higDjoCCNXSA95xZMWUdPvXNmkAduhWv

now to figure out how to get the input addresses...

thanks to this answer, we can see that both the signatures are der encoded in the following format:

  • 0x30: a header byte indicating a compound structure
  • a 1-byte length descriptor for all what follows
  • 0x02: a header byte indicating an integer
  • a 1-byte length descriptor for the r value
  • the r coordinate, as a big-endian integer
  • 0x02: a header byte indicating an integer
  • a 1-byte length descriptor for the s value
  • the s coordinate, as a big-endian integer
  • a hashtype byte

so, decoding the raw script signatures:

493046022100e26d9ff76a07d68369e5782be3f8532d25ecc8add58ee256da6c550b52e8006b022100b4431f5a9a4dcb51cbdcaae935218c0ae4cfc8aa903fe4e5bac4c208290b7d5d01
  • 0x49 = OP_PUSHDATA0 - push 73 bytes onto the stack (script command not part of the signature value)
  • 0x30 = header byte
  • 0x46 = length descriptor (70 bytes)
  • 0x02 = header byte
  • 0x21 = r value length descriptor (33 bytes)
  • 00e26d9ff76a07d68369e5782be3f8532d25ecc8add58ee256da6c550b52e8006b the r coordinate as a big endian integer
  • 0x02 = header byte
  • 0x21 = s value length descriptor (33 bytes)
  • 00b4431f5a9a4dcb51cbdcaae935218c0ae4cfc8aa903fe4e5bac4c208290b7d5d the s coordinate as a big endian integer
  • 0x01 = hashtype byte

and the second raw signature has the same format too:

493046022100a2ab7cdc5b67aca032899ea1b262f6e8181060f5a34ee667a82dac9c7b7db4c3022100911bc945c4b435df8227466433e56899fbb65833e4853683ecaa12ee840d16bf01
  • 0x49 = OP_PUSHDATA0 - push 73 bytes onto the stack (script command not part of the signature value)
  • 0x30 = header byte
  • 0x46 = length descriptor (70 bytes)
  • 0x02 = header byte
  • 0x21 = r value length descriptor (33 bytes)
  • 00a2ab7cdc5b67aca032899ea1b262f6e8181060f5a34ee667a82dac9c7b7db4c3 the r coordinate as a big endian integer
  • 0x02 = header byte
  • 0x21 = s value length descriptor (33 bytes)
  • 00911bc945c4b435df8227466433e56899fbb65833e4853683ecaa12ee840d16bf the s coordinate as a big endian integer
  • 0x01 = hashtype byte

so this confirms that the signature values in the transaction inputs actually do not contain public keys at all. the input addresses actually come from the previous transaction outputs which can be identified through the input hash and input index in the current tx.

3
2

my solution was, that I passed the hex string to:

    def publicKeyDecode(pub):
            hash1 = hashlib.sha256(binascii.unhexlify(pub))
            hash2 = hashlib.new('ripemd160', hash1.digest())
            padded = (b'\x00') + hash2.digest()
            hash3 = hashlib.sha256(padded)
            hash4 = hashlib.sha256(hash3.digest())
            padded += hash4.digest()[:4]
            return base58.b58encode(padded)
3
  • had to use sha256 instead of ripemd160 to get the correct address Mar 13, 2018 at 23:55
  • Had to comment out the first line (pub = pub[2:-2]) to work with the public key (0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352) on the wiki (en.bitcoin.it/wiki/…)
    – Pedro
    Dec 14, 2019 at 21:53
  • Everything depends on the script itself. because it is a program. so you have to interpret it on your own. The above solution was a standard script decoding. Someone edited it, so its not correct for all scripts. Feb 10, 2020 at 9:26
1

Here's a python3+ implementation for @mulllhausen's answer on parsing the Bitcoin address from the P2PKH script:

import binascii
import hashlib
import base58

def P2PKHToAddress(pkscript, istestnet=False):
    pub = pkscript[6:-4] # get pkhash, inbetween first 3 bytes and last 2 bytes
    p = '00' + pub # prefix with 00 if it's mainnet
    if istestnet:
        p = '6F' + pub # prefix with 0F if it's testnet
    h1 = hashlib.sha256(binascii.unhexlify(p))
    h2 = hashlib.new('sha256', h1.digest())
    h3 = h2.hexdigest()
    a = h3[0:8] # first 4 bytes
    c = p + a # add first 4 bytes to beginning of pkhash
    d = int(c, 16) # string to decimal
    b = d.to_bytes((d.bit_length() + 7) // 8, 'big') # decimal to bytes
    address = base58.b58encode(b) # bytes to base58
    if not istestnet:
        address = '1' + address # prefix with 1 if it's mainnet
    return address

print(P2PKHToAddress("76a91412ab8dc588ca9d5787dde7eb29569da63c3a238c88ac")) # 12higDjoCCNXSA95xZMWUdPvXNmkAduhWv

Your Answer

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

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