Bitcoin Forum
June 07, 2024, 05:26:30 AM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: python scriptpubkey OP_CHECKMULTISIG to address  (Read 129 times)
linuxqq (OP)
Jr. Member
*
Offline Offline

Activity: 34
Merit: 6


View Profile
May 17, 2021, 03:09:21 PM
Last edit: May 18, 2021, 12:29:27 AM by linuxqq
 #1

Please forgive me, I posted a request for help in another section, maybe I posted it in the wrong place, no one responded, so I posted it here, I hope I can get some help,   Hello everyone, I am new to Bitcoin, I have a problem and need help, first of all, thank you, the following is my question:
I tried to use the following code to convert the scriptPubKey in the Bitcoin transaction to an address, but why p2sh cannot be converted?

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


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 = pubkey_hex
    round1 = sha256(pubkey.encode("utf8")).digest()
    h = new('ripemd160')
    h.update(round1)
    pubkey_hash = h.digest()
    return ConvertPKHToAddress(b'\x00', pubkey_hash)


def cover_address(script_pub_key):
    script_pub_key_str=hashStr(script_pub_key)
    if script_pub_key_str[0:4]==b'76a9':
        #This is a pubkeyhash
        bytes=script_pub_key[2]  #number of bytes in the pub_key
        try:
            assert bytes==20
        except:
            return None
        public_key = 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
        return format(address2.decode())
    elif script_pub_key_str[0:2]==b'a9':
        #this is a scripthash (pay-to-script address)
        bytes=script_pub_key[1]  #number of bytes in the pub_key
        try:
            assert bytes==20
        except:
            return None
        public_key = script_pub_key[2:2+bytes] #20 bytes
        z=b'\05'+public_key  #used for mainnet
        address2=base58.b58encode_check(z)
        return address2.decode()
    elif script_pub_key_str[0:2]==b'00':
        spk = binascii.unhexlify(script_pub_key_str.decode())
        version = spk[0] - 0x50 if spk[0] else 0
        program = spk[2:]
        return bech32.encode('bc', version, program)
    else:
        #print(script_pub_key_str)
        return None

I want to convert the following p2sh scriptpubkey to an address, but I don’t know how to do it, the following is the transaction I want to  convert
Quote
{'txid': 'ca0cae6cd13e9150757612b1a3ea2e0e2d990d31098252892d032ffa73fc4f83', 'hash': 'ca0cae6cd13e9150757612b1a3ea2e0e2d990d31098252892d032ffa73fc4f83', 'version': 1, 'size': 205, 'vsize': 205, 'weight': 820, 'locktime': 0, 'vin': [{'txid': '05a9f3f1ed8099af7f37f818ce92442a1dccf9b471375bcb7dd4771db8080361', 'vout': 0, 'scriptSig': {'asm': '0 3045022041a325a85809d9b0c14b7858d8a7169f6dd847d41dbf342bfb745d76d15699c1022100c d6e77a8c3ffb95372d5ea716e0522efe121f253cf2381fd1d004204a8feeee7[ALL]', 'hex': '00483045022041a325a85809d9b0c14b7858d8a7169f6dd847d41dbf342bfb745d76d15699c1022 100cd6e77a8c3ffb95372d5ea716e0522efe121f253cf2381fd1d004204a8feeee701'}, 'sequence': 4294967295}], 'vout': [{'value': 1.999, 'n': 0, 'scriptPubKey': {'asm': '1 037953dbf08030f67352134992643d033417eaa6fcfb770c038f364ff40d761588 0002d4a196263b56e24c40a87f4f5adc89b74a17712cc540c20135fc50a2403937 2 OP_CHECKMULTISIG', 'hex': '5121037953dbf08030f67352134992643d033417eaa6fcfb770c038f364ff40d761588210002d4a 196263b56e24c40a87f4f5adc89b74a17712cc540c20135fc50a240393752ae', 'type': 'nonstandard'}}], 'hex': '0100000001610308b81d77d47dcb5b3771b4f9cc1d2a4492ce18f8377faf9980edf1f3a90500000 0004a00483045022041a325a85809d9b0c14b7858d8a7169f6dd847d41dbf342bfb745d76d15699 c1022100cd6e77a8c3ffb95372d5ea716e0522efe121f253cf2381fd1d004204a8feeee701fffff fff01603bea0b00000000475121037953dbf08030f67352134992643d033417eaa6fcfb770c038f 364ff40d761588210002d4a196263b56e24c40a87f4f5adc89b74a17712cc540c20135fc50a2403 93752ae00000000', 'blockhash': '00000000000002b211876fa753c8bf5c3b4f43198c6a20d91b26cd1ed5b71918', 'confirmations': 471187, 'time': 1355895514, 'blocktime': 1355895514}



Thank you so much for taking the time to read.
NotATether
Legendary
*
Offline Offline

Activity: 1624
Merit: 6874


bitcoincleanup.com / bitmixlist.org


View Profile WWW
May 17, 2021, 06:55:11 PM
 #2

You did not post the code for hashStr() so I cannot reproduce your example.

Are you trying to hash the ASM of the scriptPubKey, or the hex? This transaction you provided has just one vout so you're either hashing the asm as string:

Code:
1 037953dbf08030f67352134992643d033417eaa6fcfb770c038f364ff40d761588 0002d4a196263b56e24c40a87f4f5adc89b74a17712cc540c20135fc50a2403937 2 OP_CHECKMULTISIG

or the hex as a string (which doesn't make any sense, why aren't you hashing it as bytes?):

Code:
5121037953dbf08030f67352134992643d033417eaa6fcfb770c038f364ff40d761588210002d4a
196263b56e24c40a87f4f5adc89b74a17712cc540c20135fc50a240393752ae

Note the newlines in these code blocks are from your OP. Are you sure you're not hashing newlines too and that's throwing off your hash checks?

.
.BLACKJACK ♠ FUN.
█████████
██████████████
████████████
█████████████████
████████████████▄▄
░█████████████▀░▀▀
██████████████████
░██████████████
████████████████
░██████████████
████████████
███████████████░██
██████████
CRYPTO CASINO &
SPORTS BETTING
▄▄███████▄▄
▄███████████████▄
███████████████████
█████████████████████
███████████████████████
█████████████████████████
█████████████████████████
█████████████████████████
███████████████████████
█████████████████████
███████████████████
▀███████████████▀
█████████
.
linuxqq (OP)
Jr. Member
*
Offline Offline

Activity: 34
Merit: 6


View Profile
May 18, 2021, 12:32:13 AM
 #3

Thank you for your help. I published the code of hashStr. I am a beginner. I tried to convert hex to address, but I found that the address starting with 3 cannot be converted. I don’t know what is missing in my code,Thank you very much Reply.
linuxqq (OP)
Jr. Member
*
Offline Offline

Activity: 34
Merit: 6


View Profile
May 18, 2021, 08:53:43 AM
 #4

I try to parse the Hex in the following code, the actual address is 1VayNert3x1KzbpzMGt2qdqrAThiRovi8, but after I parse it, it is 16SvHaiZXXgoBxAvZPo36zsyuAxLK1qECy, I don’t know what I’m doing wrong

Code:
# coding:utf-8
from bip32utils import Base58
import bech32
from hashlib import *
from base58 import *
import base58
import binascii


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

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)


print(PubkeyToAddress('4104a39b9e4fbd213ef24bb9be69de4a118dd0644082e47c01fd9159d38637b83fbcdc115a5d6e970586a012d1cfe3e3a8b1a3d04e763bdc5a071c0e827c0bd834a5ac'))

b'2hoLE1uiNFYJTgjGf58K3Vy8RBz7AeqZyD'
NotATether
Legendary
*
Offline Offline

Activity: 1624
Merit: 6874


bitcoincleanup.com / bitmixlist.org


View Profile WWW
May 18, 2021, 10:11:03 AM
Merited by ABCbits (1), linuxqq (1)
 #5

I analyzed your first example and found that you're trying to compare the hash of a multisig scriptPubKey asm with P2SH asm bytes. "a9" stands for OP_HASH160 which is not used in direct multisig. In other words your code will work with multisig wrapped in P2SH but not "raw" multisig where you insert the script by itself without P2SH opcodes.

There is technically no address format for raw multisig (see https://learnmeabitcoin.com/technical/p2ms) which is why they're wrapped around P2SH in the first place. If there were such an address format, you'd simply be able to feed the asm in bytes into the cover_address function.

.
.BLACKJACK ♠ FUN.
█████████
██████████████
████████████
█████████████████
████████████████▄▄
░█████████████▀░▀▀
██████████████████
░██████████████
████████████████
░██████████████
████████████
███████████████░██
██████████
CRYPTO CASINO &
SPORTS BETTING
▄▄███████▄▄
▄███████████████▄
███████████████████
█████████████████████
███████████████████████
█████████████████████████
█████████████████████████
█████████████████████████
███████████████████████
█████████████████████
███████████████████
▀███████████████▀
█████████
.
linuxqq (OP)
Jr. Member
*
Offline Offline

Activity: 34
Merit: 6


View Profile
May 18, 2021, 03:23:46 PM
 #6

I analyzed your first example and found that you're trying to compare the hash of a multisig scriptPubKey asm with P2SH asm bytes. "a9" stands for OP_HASH160 which is not used in direct multisig. In other words your code will work with multisig wrapped in P2SH but not "raw" multisig where you insert the script by itself without P2SH opcodes.

There is technically no address format for raw multisig (see https://learnmeabitcoin.com/technical/p2ms) which is why they're wrapped around P2SH in the first place. If there were such an address format, you'd simply be able to feed the asm in bytes into the cover_address function.

Thanks again for your help
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!