Post
Topic
Board Bitcoin Technical Support
Merits 2 from 2 users
Re: Pubkey/address help needed (Python)
by
NotATether
on 11/01/2022, 10:28:24 UTC
⭐ Merited by ETFbitcoin (1) ,AdolfinWolf (1)
There is a helpful blog post at https://matthewdowney.github.io/create-segwit-address.htmlwhich provides the code to generate the P2SH address from a public key with minimal dependencies.

This is the only thing that needs to be installed:

Code:
(base) zenulabidin@artanis:~/Documents$  pip install git+https://github.com/matthewdowney/bip32utils
Collecting git+https://github.com/matthewdowney/bip32utils
  Cloning https://github.com/matthewdowney/bip32utils to /tmp/pip-req-build-bqskxgsa
  Running command git clone -q https://github.com/matthewdowney/bip32utils /tmp/pip-req-build-bqskxgsa
Requirement already satisfied: ecdsa in /home/zenulabidin/anaconda3/lib/python3.8/site-packages/ecdsa-0.16.1-py3.8.egg (from bip32utils==0.3.post3) (0.16.1)
Requirement already satisfied: six>=1.9.0 in /home/zenulabidin/anaconda3/lib/python3.8/site-packages (from ecdsa->bip32utils==0.3.post3) (1.15.0)
Building wheels for collected packages: bip32utils
  Building wheel for bip32utils (setup.py) ... done
  Created wheel for bip32utils: filename=bip32utils-0.3.post3-py3-none-any.whl size=10415 sha256=105abc933ae4057dd876b844ec6efc2167c31c9679e6997d187bd8ae186d16a4
  Stored in directory: /tmp/pip-ephem-wheel-cache-7_7ylb1d/wheels/04/0c/5b/e5ed2d7087a4d71bcfb1491071e94c657e4b3eeeb09bb362d2
Successfully built bip32utils
Installing collected packages: bip32utils
Successfully installed bip32utils-0.3.post3

Then you can run the code in the link:

Code:
import hashlib
def hash160(x): # Both accepts & returns bytes
    return hashlib.new('ripemd160', hashlib.sha256(x).digest()).digest()

from bip32utils import Base58

def p2wpkh_in_p2sh_addr(pk, testnet=False):
    """
    Compressed public key (hex string) -> p2wpkh nested in p2sh address. 'SegWit address.'
    """
    # Script sig is just PUSH(20){hash160(cpk)}
    push_20 = bytes.fromhex("0014")
    script_sig = push_20 + hash160(bytes.fromhex(pk))
   
    # Address is then prefix + hash160(script_sig)
    prefix = b"\xc4" if testnet else b"\x05"
    address = Base58.check_encode(prefix + hash160(script_sig))
    return address

>>> pub = "03a1af804ac108a8a51782198c2d034b28bf90c8803f5a53f76276fa69a4eae77f"
>>> p2wpkh_in_p2sh_addr(pub)
"36NvZTcMsMowbt78wPzJaHHWaNiyR73Y4g"
>>> p2wpkh_in_p2sh_addr(pub, testnet=True)
"2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2"

I ran the examples above and I was able to reproduce them (there is a small function error in the original post, hash160_bytes should be just hash160).