6

I'm looking for a way to get address from scriptSig. I want to know input address. Can you share how to do it? I prefer PHP library but any ways would be appreciated.

e.g.

I use bitwasp, a PHP library. I can see a scriptSig ("483...767") in vin. I want to decode it so that I can get the source addresses.

PHP sample

<?php

require_once 'vendor/autoload.php';

use BitWasp\BitcoinLib\RawTransaction;

$hex = '0100000001e7bb795fa90136f4052a99a433a16d71406261dec7eaff2a2a03ce7254bb4159010000006b483045022100f5b10c765ae5116917ddf9b8c4e8d07996b37ad934c005396e7dcda70e7621ee022014cf65f5cc46e229fbcfe7259b3f8c9d0b0c3cd446c4307a8872ad6cc0d538b401210396f8781a4900372a5d72d84718d146170d5983e67dff8b4a28fef80690c09767ffffffff035f150000000000001976a9143e37de641b25616304415a72bc556824f442004588ac00000000000000001e6a1c54f55fe6f2a0f349e2921d06e63d58712a906fbb4231f1e943da82d6313d1300000000001976a9142f7dcdf7cda481fe0f123d4c62bf830605e9f54d88ac00000000';

$tx_data = RawTransaction::decode($hex);
print(json_encode($tx_data));

Output

{
   "txid":"55a8f0d5852745ab2d80358ff4ae6fdbfeab0e4dc94b3474d1c5538e0579bb95",
   "version":"1",
   "vin":[
      {
         "txid":"5941bb5472ce032a2affeac7de616240716da133a4992a05f43601a95f79bbe7",
         "vout":1,
         "scriptSig":{
            "asm":"3045022100f5b10c765ae5116917ddf9b8c4e8d07996b37ad934c005396e7dcda70e7621ee022014cf65f5cc46e229fbcfe7259b3f8c9d0b0c3cd446c4307a8872ad6cc0d538b401 0396f8781a4900372a5d72d84718d146170d5983e67dff8b4a28fef80690c09767",
            "hex":"483045022100f5b10c765ae5116917ddf9b8c4e8d07996b37ad934c005396e7dcda70e7621ee022014cf65f5cc46e229fbcfe7259b3f8c9d0b0c3cd446c4307a8872ad6cc0d538b401210396f8781a4900372a5d72d84718d146170d5983e67dff8b4a28fef80690c09767"
         },
         "sequence":4294967295
      }
   ],
   "vout":[
      {
         "value":"0.00005471",
         "vout":0,
         "scriptPubKey":{
            "asm":"OP_DUP OP_HASH160 3e37de641b25616304415a72bc556824f4420045 OP_EQUALVERIFY OP_CHECKSIG",
            "hex":"76a9143e37de641b25616304415a72bc556824f442004588ac",
            "type":"pubkeyhash",
            "reqSigs":1,
            "hash160":"3e37de641b25616304415a72bc556824f4420045",
            "addresses":[
               "16fypikbjmmfroCHUhDLhczngCfL6BgccH"
            ]
         }
      },
      {
         "value":"0.00000000",
         "vout":1,
         "scriptPubKey":{
            "asm":"OP_RETURN 54f55fe6f2a0f349e2921d06e63d58712a906fbb4231f1e943da82d6",
            "hex":"6a1c54f55fe6f2a0f349e2921d06e63d58712a906fbb4231f1e943da82d6",
            "message":"unable to decode tx type!"
         }
      },
      {
         "value":"0.01260849",
         "vout":2,
         "scriptPubKey":{
            "asm":"OP_DUP OP_HASH160 2f7dcdf7cda481fe0f123d4c62bf830605e9f54d OP_EQUALVERIFY OP_CHECKSIG",
            "hex":"76a9142f7dcdf7cda481fe0f123d4c62bf830605e9f54d88ac",
            "type":"pubkeyhash",
            "reqSigs":1,
            "hash160":"2f7dcdf7cda481fe0f123d4c62bf830605e9f54d",
            "addresses":[
               "15L7U55PAsHLEpQkZqz62e3eqWd9AHb2DH"
            ]
         }
      }
   ],
   "locktime":"0"
}

Update 1

The following is a screenshot of blockchain.info

enter image description here

https://blockchain.info/ja/tx/10857ad56f1695559562af8076aea4ccba625ba79a82f75e5658c0c2fa4336c0

I'm wondering how I can get the source address "1J16FUpZsS6My1FqHXpka5fztAnyFsBPf1".


Update 2

I found a similar question and retrieving previous transaction was proposed. It may work but I want to decode hex so that it can reduce cost to access bitcoind.

How to get the Input Address from vin where only a txid is given (Insight-Api)


Update 3

This is also taking same approach. It may impossible to decode the scriptsig...

How to findout the sender of a transaction


Update 4

This explains why it is impossible. Okay I give up decoding scriptsig. I'll retrieve it by txid.

Due to the nature of the pay-to-pubkey script, the script sig does not contain the pubkey anymore (just the signature).

https://stackoverflow.com/questions/29350766/extract-input-address-from-a-namecoin-transaction-given-a-name-operation


Update 5 (Solved)

theStack gave me the best answer. Following the answer, I tried it in PHP with Bitwasp.

<?php

require_once 'vendor/autoload.php';

use BitWasp\BitcoinLib\BitcoinLib;
use BitWasp\BitcoinLib\RawTransaction;

$hex = '0100000001e7bb795fa90136f4052a99a433a16d71406261dec7eaff2a2a03ce7254bb4159010000006b483045022100f5b10c765ae5116917ddf9b8c4e8d07996b37ad934c005396e7dcda70e7621ee022014cf65f5cc46e229fbcfe7259b3f8c9d0b0c3cd446c4307a8872ad6cc0d538b401210396f8781a4900372a5d72d84718d146170d5983e67dff8b4a28fef80690c09767ffffffff035f150000000000001976a9143e37de641b25616304415a72bc556824f442004588ac00000000000000001e6a1c54f55fe6f2a0f349e2921d06e63d58712a906fbb4231f1e943da82d6313d1300000000001976a9142f7dcdf7cda481fe0f123d4c62bf830605e9f54d88ac00000000';

$tx = RawTransaction::decode($hex);

$asm = explode(' ', $tx['vin'][0]['scriptSig']['asm']);
$address = BitcoinLib::public_key_to_address($asm[1], '00');

print($address); // 15L7U55PAsHLEpQkZqz62e3eqWd9AHb2DHyusaku
1
  • does this work with P2SH tx ?
    – user10603
    Jan 4, 2018 at 6:30

1 Answer 1

9

The scriptSig needed for spending a P2PKH output (that is, an output of a standard address starting with '1...') consists of two parts, namely the signature and the public key. Looking at your example transaction 10857ad56f1695559562af8076aea4ccba625ba79a82f75e5658c0c2fa4336c0, the public key is 03d7b3bc2d0b4b72a845c469c9fee3c8cf475a2f237e379d7f75a4f463f7bd6ebd:

enter image description here

From this you can derive the address by first applying the HASH-160 (where HASH-160(x) = RIPEMD-160(SHA-256(x))), then adding network byte (prefix) and checksum (postfix), and finally converting the whole data into Base58 format. The detailed process of converting a public key to an address is described here: https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses

Though you probably have Bitcoin libraries doing the dirty work, the following small Python script converts the public key to the address:

 #!/usr/bin/env python
 from hashlib import *
 from base58 import *

def SHA256D(bstr):
    return sha256(sha256(bstr).digest()).digest()

def ConvertPKHToAddress(prefix, addr):
    data = prefix + addr
    return b58encode(data + SHA256D(data)[:4])

def PubkeyToAddress(pubkey_hex):
    pubkey = bytearray.fromhex(pubkey_hex)
    round1 = sha256(pubkey).digest()
    h = new('ripemd160')
    h.update(round1)
    pubkey_hash = h.digest()
    return ConvertPKHToAddress(b'\x00', pubkey_hash)

pubkey = "03d7b3bc2d0b4b72a845c469c9fee3c8cf475a2f237e379d7f75a4f463f7bd6ebd"
print("Address: %s" % PubkeyToAddress(pubkey))

This leads to the following expected result:

$ ./pubkey_to_script.py
Address: 1J16FUpZsS6My1FqHXpka5fztAnyFsBPf1
4
  • 1
    Thanks! I've confirmed it in PHP with Bitwasp library and posted the source code above. You are awesome!
    – zono
    Mar 6, 2017 at 14:49
  • 1
    I'm glad I could help! Note that this approach only works when the output of a P2PKH address is used as input. For P2SH addresses (that is, starting with '3...', mostly used for multisignature purposes) the sigScript can look quite different. Though very unlikely, there could be cases where you can't exactly tell from the scriptSig alone whether it was spent from a P2PKH or P2SH address and hence can't decide which prefix to use. Maybe this is the reason why in most answers people suggest to lookup the previous tx output.
    – theStack
    Mar 6, 2017 at 16:09
  • 1
    Thank you for letting me know important things. I will consider about that. I think I will add checking whether P2PKH or P2SH before getting address. I guess most locking script nowadays are P2PKH. I will lookup bitcoind only non-P2PKH address so that I can reduce cost of access to bitcoind.
    – zono
    Mar 6, 2017 at 17:01
  • I translated this code from python to golang: gist.github.com/IvRRimum/2457e18092292e89eb7ee218c7dc70da
    – IvRRimUm
    Mar 6, 2022 at 17:25

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.