def extract_public_key(bytes): decoded = [x for x in script_GetOp(bytes)] # non-generated TxIn transactions push a signature # (seventy-something bytes) and then their public key # (65 bytes) onto the stack: match = [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[1][1]) # The Genesis Block, self-payments, and pay-by-IP-address payments look like: # 65 BYTES:... CHECKSIG match = [opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1]) # Pay-by-Bitcoin-address TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1]) # OP_EVAL TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_EVAL] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1], version="\x01") return "(None)"
def extract_public_key(bytes): decoded = [x for x in script_GetOp(bytes)] # non-generated TxIn transactions push a signature # (seventy-something bytes) and then their public key # (65 bytes) onto the stack: match = [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[1][1]) # The Genesis Block, self-payments, and pay-by-IP-address payments look like: # 65 BYTES:... CHECKSIG match = [opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1]) # Pay-by-Bitcoin-address TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1]) # OP_EVAL TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_EVAL ] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1], version="\x01") return "(None)"
def extract_public_key(bytes, version='\x00'): try: decoded = [ x for x in script_GetOp(bytes) ] except struct.error: return "(None)" match = [ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4 ] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[1][1], version=version) match = [ opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1], version=version) match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1], version=version) multisigs = [ [ opcodes.OP_1, opcodes.OP_PUSHDATA4, opcodes.OP_1, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_2, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_2, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_3, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_3, opcodes.OP_CHECKMULTISIG ] ] for match in multisigs: if match_decoded(decoded, match): return "["+','.join([public_key_to_bc_address(decoded[i][1]) for i in range(1,len(decoded)-1)])+"]" match = [ opcodes.OP_HASH160, 0x14, opcodes.OP_EQUAL ] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[1][1], version="\x05") return "(None)"
def extract_public_key(bytes, version='\x00'): try: decoded = [x for x in script_GetOp(bytes)] except struct.error: return "(None)" # non-generated TxIn transactions push a signature # (seventy-something bytes) and then their public key # (33 or 65 bytes) onto the stack: match = [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[1][1], version=version) # The Genesis Block, self-payments, and pay-by-IP-address payments look like: # 65 BYTES:... CHECKSIG match = [opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1], version=version) # Pay-by-Bitcoin-address TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1], version=version) # BIP11 TxOuts look like one of these: multisigs = [[ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_1, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_2, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_3, opcodes.OP_CHECKMULTISIG ]] for match in multisigs: if match_decoded(decoded, match): return "[" + ','.join([ public_key_to_bc_address(decoded[i][1]) for i in range(1, len(decoded) - 1) ]) + "]" # BIP16 TxOuts look like: # HASH160 20 BYTES:... EQUAL match = [opcodes.OP_HASH160, 0x14, opcodes.OP_EQUAL] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[1][1], version="\x05") return "(None)"
def extract_public_key(bytes, version='\x00'): try: decoded = [ x for x in script_GetOp(bytes) ] except (struct.error, IndexError): return None # non-generated TxIn transactions push a signature # (seventy-something bytes) and then their public key # (33 or 65 bytes) onto the stack: match = [ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4 ] if match_decoded(decoded, match): if (decoded[0][0]==0 and decoded[1][0] in [20, 32]): #Native Segwit P2PKH or P2SH output #Return the exact bytes return decoded[1][1] return public_key_to_bc_address(decoded[1][1], version=version) # The Genesis Block, self-payments, and pay-by-IP-address payments look like: # 65 BYTES:... CHECKSIG match = [ opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1], version=version) # Pay-by-Bitcoin-address TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1], version=version) # BIP11 TxOuts look like one of these: # Note that match_decoded is dumb, so OP_1 actually matches OP_1/2/3/etc: multisigs = [ [ opcodes.OP_1, opcodes.OP_PUSHDATA4, opcodes.OP_1, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_2, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_2, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_3, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_3, opcodes.OP_CHECKMULTISIG ] ] for match in multisigs: if match_decoded(decoded, match): return [public_key_to_bc_address(decoded[i][1], version=version) for i in range(1,len(decoded)-1)] # BIP16 TxOuts look like: # HASH160 20 BYTES:... EQUAL match = [ opcodes.OP_HASH160, 0x14, opcodes.OP_EQUAL ] if match_decoded(decoded, match): script_version = '\x05' if version=='\x00' else '\xC4' return hash_160_to_bc_address(decoded[1][1], version=script_version) return None
def extract_public_key(bytes, version='\x00'): try: decoded = [x for x in script_GetOp(bytes)] except struct.error: return "(None)" # non-generated TxIn transactions push a signature # (seventy-something bytes) and then their public key # (33 or 65 bytes) onto the stack: match = [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[1][1], version=version) # The Genesis Block, self-payments, and pay-by-IP-address payments look like: # 65 BYTES:... CHECKSIG match = [opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1], version=version) # Pay-by-Bitcoin-address TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1], version=version) # BIP11 TxOuts look like one of these: multisigs = [ [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_1, opcodes.OP_CHECKMULTISIG], [ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_2, opcodes.OP_CHECKMULTISIG ], [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_3, opcodes.OP_CHECKMULTISIG] ] for match in multisigs: if match_decoded(decoded, match): return "[" + ','.join([public_key_to_bc_address(decoded[i][1]) for i in range(1, len(decoded) - 1)]) + "]" # BIP16 TxOuts look like: # HASH160 20 BYTES:... EQUAL match = [opcodes.OP_HASH160, 0x14, opcodes.OP_EQUAL] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[1][1], version="\x05") return "(None)"
def parse_TxOut(vds): d = {} d['value'] = vds.read_int64() raw = vds.read_bytes(vds.read_compact_size()) d['scriptPubKey'] = raw if len(raw) == 25 and raw[0] == '\x76' and raw[1] == '\xa9' and raw[2] == '\x14': d['address'] = base58.hash_160_to_bc_address(raw[3:-2]) return d
def extract_public_key(bytes, version='\x00'): try: decoded = [x for x in script_GetOp(bytes)] except struct.error: return "(None)" match = [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[1][1], version=version) match = [opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1], version=version) match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1], version=version) multisigs = [[ opcodes.OP_1, opcodes.OP_PUSHDATA4, opcodes.OP_1, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_2, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_2, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_3, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_3, opcodes.OP_CHECKMULTISIG ]] for match in multisigs: if match_decoded(decoded, match): return "[" + ','.join([ public_key_to_bc_address(decoded[i][1]) for i in range(1, len(decoded) - 1) ]) + "]" match = [opcodes.OP_HASH160, 0x14, opcodes.OP_EQUAL] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[1][1], version="\x05") return "(None)"
k = ecdsa_ssl.KEY() k.generate(('%064x' % PRIVATE_KEY).decode('hex')) #here we retrieve the public key data generated from the supplied private key pubkey_data = k.get_pubkey() #then we create a signature over the hash of the signature-less transaction sig_data=k.sign(hash_scriptless) #a one byte "hash type" is appended to the end of the signature (https://en.bitcoin.it/wiki/OP_CHECKSIG) sig_data = sig_data + chr(SIGHASH_ALL) #let's check that the provided privat key can actually redeem the output in question if (bc_address_to_hash_160(public_key_to_bc_address(pubkey_data)) != tx_info['txOut'][OUTPUT_INDEX]['scriptPubKey'][3:-2]): bytes = b58decode(SEND_TO_ADDRESS, 25) raise RuntimeError, "The supplied private key cannot be used to redeem output index %d\nYou need to supply the private key for address %s" % \ (OUTPUT_INDEX, hash_160_to_bc_address(tx_info['txOut'][OUTPUT_INDEX]['scriptPubKey'][3:-2], bytes[0])) ##now we begin creating the final transaction. this is a duplicate of the signature-less transaction, ## with the scriptSig filled out with a script that pushes the signature plus one-byte hash code type, and public key from above, to the stack final_tx = BCDataStream() final_tx.write_int32(tx_fields['version']) final_tx.write_compact_size(tx_fields['num_txin']) final_tx.write(tx_fields['prevout_hash']) final_tx.write_uint32(tx_fields['output_index']) ##now we need to write the actual scriptSig. ## this consists of the DER-encoded values r and s from the signature, a one-byte hash code type, and the public key in uncompressed format ## we also need to prepend the length of these two data pieces (encoded as a single byte ## containing the length), before each data piece. this length is a script opcode that tells the ## Bitcoin script interpreter to push the x following bytes onto the stack
def rawpk2addr(pk_script): """ Convert a raw bitcoin block script of public key to a common address """ import base58 # reference program: base58.py return base58.hash_160_to_bc_address(rawpk2hash160(pk_script))
def extract_public_key(bytes, version='\x00'): try: decoded = [x for x in script_GetOp(bytes)] except (struct.error, IndexError): return None # non-generated TxIn transactions push a signature # (seventy-something bytes) and then their public key # (33 or 65 bytes) onto the stack: match = [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4] if match_decoded(decoded, match): if (decoded[0][0] == 0 and decoded[1][0] in [20, 32]): #Native Segwit P2PKH or P2SH output #Return the exact bytes return decoded[1][1] return public_key_to_bc_address(decoded[1][1], version=version) # The Genesis Block, self-payments, and pay-by-IP-address payments look like: # 65 BYTES:... CHECKSIG match = [opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG] if match_decoded(decoded, match): return public_key_to_bc_address(decoded[0][1], version=version) # Pay-by-Bitcoin-address TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] if match_decoded(decoded, match): return hash_160_to_bc_address(decoded[2][1], version=version) # BIP11 TxOuts look like one of these: # Note that match_decoded is dumb, so OP_1 actually matches OP_1/2/3/etc: multisigs = [[ opcodes.OP_1, opcodes.OP_PUSHDATA4, opcodes.OP_1, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_2, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_2, opcodes.OP_CHECKMULTISIG ], [ opcodes.OP_3, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_3, opcodes.OP_CHECKMULTISIG ]] for match in multisigs: if match_decoded(decoded, match): return [ public_key_to_bc_address(decoded[i][1], version=version) for i in range(1, len(decoded) - 1) ] # BIP16 TxOuts look like: # HASH160 20 BYTES:... EQUAL match = [opcodes.OP_HASH160, 0x14, opcodes.OP_EQUAL] if match_decoded(decoded, match): script_version = '\x05' if version == '\x00' else '\xC4' return hash_160_to_bc_address(decoded[1][1], version=script_version) return None
def hash_160_to_bc_address(h160, addrtype=0): """Deprecated.""" return base58.hash_160_to_bc_address(h160, addrtype)