def pubkeyhash_to_pubkey(pubkeyhash, provided_pubkeys=None): # Search provided pubkeys. if provided_pubkeys: if type(provided_pubkeys) != list: provided_pubkeys = [provided_pubkeys] for pubkey in provided_pubkeys: if pubkeyhash == script.pubkey_to_pubkeyhash(util.unhexlify(pubkey)): return pubkey # Search blockchain. raw_transactions = searchrawtransactions(pubkeyhash, unconfirmed=True) for tx in raw_transactions: for vin in tx['vin']: if 'coinbase' not in vin: scriptsig = vin['scriptSig'] asm = scriptsig['asm'].split(' ') if len(asm) >= 2: # catch unhexlify errs for when asm[1] isn't a pubkey (eg; for P2SH) try: pubkey = asm[1] if pubkeyhash == script.pubkey_to_pubkeyhash(util.unhexlify(pubkey)): return pubkey except binascii.Error: pass raise UnknownPubKeyError('Public key was neither provided nor published in blockchain.')
def pubkeyhash_to_pubkey(pubkeyhash, provided_pubkeys=None): # Search provided pubkeys. if provided_pubkeys: if type(provided_pubkeys) != list: provided_pubkeys = [provided_pubkeys] for pubkey in provided_pubkeys: if pubkeyhash == script.pubkey_to_pubkeyhash( util.unhexlify(pubkey)): return pubkey # Search blockchain. raw_transactions = search_raw_transactions(pubkeyhash, unconfirmed=True) for tx in raw_transactions: for vin in tx['vin']: if 'coinbase' not in vin: scriptsig = vin['scriptSig'] asm = scriptsig['asm'].split(' ') if len(asm) >= 2: # catch unhexlify errs for when asm[1] isn't a pubkey (eg; for P2SH) try: pubkey = asm[1] if pubkeyhash == script.pubkey_to_pubkeyhash( util.unhexlify(pubkey)): return pubkey except binascii.Error: pass raise UnknownPubKeyError( 'Public key was neither provided nor published in blockchain.')
def decode_data_redeem_script(redeemScript): script_len = len(redeemScript) if script_len == 41 and \ redeemScript[0] == bitcoinlib.core.script.OP_DROP and \ redeemScript[35] == bitcoinlib.core.script.OP_CHECKSIGVERIFY and \ redeemScript[37] == bitcoinlib.core.script.OP_DROP and \ redeemScript[38] == bitcoinlib.core.script.OP_DEPTH and \ redeemScript[39] == bitcoinlib.core.script.OP_0 and \ redeemScript[40] == bitcoinlib.core.script.OP_EQUAL: # - OP_DROP [push] [33-byte pubkey] OP_CHECKSIGVERIFY [n] OP_DROP OP_DEPTH 0 OP_EQUAL pubkey = redeemScript[2:35] source = script.pubkey_to_pubkeyhash(pubkey) redeem_script_is_valid = True elif script_len > 41 and \ redeemScript[0] == bitcoinlib.core.script.OP_DROP and \ redeemScript[script_len-4] == bitcoinlib.core.script.OP_DROP and \ redeemScript[script_len-3] == bitcoinlib.core.script.OP_DEPTH and \ redeemScript[script_len-2] == bitcoinlib.core.script.OP_0 and \ redeemScript[script_len-1] == bitcoinlib.core.script.OP_EQUAL: # - OP_DROP {arbitrary multisig script} [n] OP_DROP OP_DEPTH 0 OP_EQUAL pubkey = None source = None redeem_script_is_valid = True else: pubkey = None source = None redeem_script_is_valid = False return pubkey, source, redeem_script_is_valid
def pubkeyhash_to_pubkey(pubkeyhash, provided_pubkeys=None): # Search provided pubkeys. if provided_pubkeys: if type(provided_pubkeys) != list: provided_pubkeys = [provided_pubkeys] for pubkey in provided_pubkeys: if pubkeyhash == script.pubkey_to_pubkeyhash(util.unhexlify(pubkey)): return pubkey # Search blockchain. raw_transactions = searchrawtransactions(pubkeyhash, unconfirmed=True) for tx in raw_transactions: for vin in tx['vin']: scriptsig = vin['scriptSig'] asm = scriptsig['asm'].split(' ') if len(asm) >= 2: pubkey = asm[1] if pubkeyhash == script.pubkey_to_pubkeyhash(util.unhexlify(pubkey)): return pubkey raise UnknownPubKeyError('Public key was neither provided nor published in blockchain.')
def pubkeyhash_to_pubkey(pubkeyhash, provided_pubkeys=None): # Search provided pubkeys. if provided_pubkeys: if type(provided_pubkeys) != list: provided_pubkeys = [provided_pubkeys] for pubkey in provided_pubkeys: if pubkeyhash == script.pubkey_to_pubkeyhash( util.unhexlify(pubkey)): return pubkey # Search blockchain. raw_transactions = searchrawtransactions(pubkeyhash) for tx in raw_transactions: for vin in tx['vin']: scriptsig = vin['scriptSig'] asm = scriptsig['asm'].split(' ') pubkey = asm[1] if pubkeyhash == script.pubkey_to_pubkeyhash( util.unhexlify(pubkey)): return pubkey # Public key for address neither provided nor published in the blockchain. return None
def get_pubkey_monosig(pubkeyhash, pubkey_resolver=input_pubkey): if wallet.is_valid(pubkeyhash): # If in wallet, get from wallet. logging.debug('Looking for public key for `{}` in wallet.'.format(pubkeyhash)) if wallet.is_mine(pubkeyhash): pubkey = wallet.get_pubkey(pubkeyhash) if pubkey: return pubkey logging.debug('Public key for `{}` not found in wallet.'.format(pubkeyhash)) # If in blockchain (and not in wallet), get from blockchain. logging.debug('Looking for public key for `{}` in blockchain.'.format(pubkeyhash)) try: pubkey = util.api('search_pubkey', {'pubkeyhash': pubkeyhash, 'provided_pubkeys': None}) except util.RPCError as e: pubkey = None if pubkey: return pubkey logging.debug('Public key for `{}` not found in blockchain.'.format(pubkeyhash)) # If not in wallet and not in blockchain, get from user. answer = pubkey_resolver(pubkeyhash) if not answer: return None # Public Key or Private Key? is_fully_valid_pubkey = True try: is_fully_valid_pubkey = script.is_fully_valid(binascii.unhexlify(answer)) except binascii.Error: is_fully_valid_pubkey = False if is_fully_valid_pubkey: logging.debug('Answer was a fully valid public key.') pubkey = answer else: logging.debug('Answer was not a fully valid public key. Assuming answer was a private key.') private_key = answer try: pubkey = script.private_key_to_public_key(private_key) except script.AltcoinSupportError: raise InputError('invalid private key') if pubkeyhash != script.pubkey_to_pubkeyhash(binascii.unhexlify(bytes(pubkey, 'utf-8'))): raise InputError('provided public or private key does not match the source address') return pubkey return None
def get_pubkey_monosig(pubkeyhash, pubkey_resolver=input_pubkey): if wallet.is_valid(pubkeyhash): # If in wallet, get from wallet. logging.debug("Looking for public key for `{}` in wallet.".format(pubkeyhash)) if wallet.is_mine(pubkeyhash): pubkey = wallet.get_pubkey(pubkeyhash) if pubkey: return pubkey logging.debug("Public key for `{}` not found in wallet.".format(pubkeyhash)) # If in blockchain (and not in wallet), get from blockchain. logging.debug("Looking for public key for `{}` in blockchain.".format(pubkeyhash)) try: pubkey = util.api("search_pubkey", {"pubkeyhash": pubkeyhash, "provided_pubkeys": None}) except util.RPCError as e: pubkey = None if pubkey: return pubkey logging.debug("Public key for `{}` not found in blockchain.".format(pubkeyhash)) # If not in wallet and not in blockchain, get from user. answer = pubkey_resolver(pubkeyhash) if not answer: return None # Public Key or Private Key? is_fully_valid_pubkey = True try: is_fully_valid_pubkey = script.is_fully_valid(binascii.unhexlify(answer)) except binascii.Error: is_fully_valid_pubkey = False if is_fully_valid_pubkey: logging.debug("Answer was a fully valid public key.") pubkey = answer else: logging.debug("Answer was not a fully valid public key. Assuming answer was a private key.") private_key = answer try: pubkey = script.private_key_to_public_key(private_key) except script.AltcoinSupportError: raise InputError("invalid private key") if pubkeyhash != script.pubkey_to_pubkeyhash(binascii.unhexlify(bytes(pubkey, "utf-8"))): raise InputError("provided public or private key does not match the source address") return pubkey return None
def decode_checkmultisig(asm): pubkeys, signatures_required = script.get_checkmultisig(asm) chunk = b'' for pubkey in pubkeys[:-1]: # (No data in last pubkey.) chunk += pubkey[1:-1] # Skip sign byte and nonce byte. chunk = arc4_decrypt(chunk) if chunk[1:len(config.PREFIX) + 1] == config.PREFIX: # Data # Padding byte in each output (instead of just in the last one) so that encoding methods may be mixed. Also, it’s just not very much data. chunk_length = chunk[0] chunk = chunk[1:chunk_length + 1] destination, data = None, chunk[len(config.PREFIX):] else: # Destination pubkeyhashes = [script.pubkey_to_pubkeyhash(pubkey) for pubkey in pubkeys] destination, data = script.construct_array(signatures_required, pubkeyhashes, len(pubkeyhashes)), None return destination, data
def decode_checkmultisig(asm): pubkeys, signatures_required = script.get_checkmultisig(asm) chunk = b'' for pubkey in pubkeys[:-1]: # (No data in last pubkey.) chunk += pubkey[1:-1] # Skip sign byte and nonce byte. chunk = arc4_decrypt(chunk) if chunk[1:len(config.PREFIX) + 1] == config.PREFIX: # Data # Padding byte in each output (instead of just in the last one) so that encoding methods may be mixed. Also, it’s just not very much data. chunk_length = chunk[0] chunk = chunk[1:chunk_length + 1] destination, data = None, chunk[len(config.PREFIX):] else: # Destination pubkeyhashes = [ script.pubkey_to_pubkeyhash(pubkey) for pubkey in pubkeys ] destination, data = script.construct_array(signatures_required, pubkeyhashes, len(pubkeyhashes)), None return destination, data
def decode_data_redeem_script(redeemScript, p2sh_is_segwit=False): script_len = len(redeemScript) found_data = b'' if script_len == 41 and \ redeemScript[0] == bitcoinlib.core.script.OP_DROP and \ redeemScript[35] == bitcoinlib.core.script.OP_CHECKSIGVERIFY and \ redeemScript[37] == bitcoinlib.core.script.OP_DROP and \ redeemScript[38] == bitcoinlib.core.script.OP_DEPTH and \ redeemScript[39] == bitcoinlib.core.script.OP_0 and \ redeemScript[40] == bitcoinlib.core.script.OP_EQUAL: # - OP_DROP [push] [33-byte pubkey] OP_CHECKSIGVERIFY [n] OP_DROP OP_DEPTH 0 OP_EQUAL pubkey = redeemScript[2:35] if p2sh_is_segwit: source = script.pubkey_to_p2whash(pubkey) else: source = script.pubkey_to_pubkeyhash(pubkey) redeem_script_is_valid = True elif script_len > 41 and \ redeemScript[0] == bitcoinlib.core.script.OP_DROP and \ redeemScript[script_len-4] == bitcoinlib.core.script.OP_DROP and \ redeemScript[script_len-3] == bitcoinlib.core.script.OP_DEPTH and \ redeemScript[script_len-2] == bitcoinlib.core.script.OP_0 and \ redeemScript[script_len-1] == bitcoinlib.core.script.OP_EQUAL: # - OP_DROP {arbitrary multisig script} [n] OP_DROP OP_DEPTH 0 OP_EQUAL pubkey = None source = None redeem_script_is_valid = True else: pubkey = None source = None redeem_script_is_valid = False try: opcode = bitcoinlib.core.script.CScriptOp(redeemScript[0]) if opcode > bitcoinlib.core.script.OP_0 and opcode < bitcoinlib.core.script.OP_PUSHDATA1 or \ opcode in (bitcoinlib.core.script.OP_PUSHDATA1, bitcoinlib.core.script.OP_PUSHDATA2, bitcoinlib.core.script.OP_PUSHDATA4): pos = 0 pos, found_data = decode_data_push(redeemScript, 0) if redeemScript[pos] == bitcoinlib.core.script.OP_DROP: pos += 1 valid_sig = False opcode = redeemScript[pos] if type(opcode) != type(''): if opcode >= bitcoinlib.core.script.OP_2 and opcode <= bitcoinlib.core.script.OP_15: # it's multisig req_sigs = opcode - bitcoinlib.core.script.OP_1 + 1 pos += 1 pubkey = None num_sigs = 0 found_sigs = False while not found_sigs: pos, npubkey = decode_data_push( redeemScript, pos) num_sigs += 1 if redeemScript[ pos] - bitcoinlib.core.script.OP_1 + 1 == num_sigs: found_sigs = True pos += 1 valid_sig = redeemScript[ pos] == bitcoinlib.core.script.OP_CHECKMULTISIGVERIFY else: # it's p2pkh pos, pubkey = decode_data_push(redeemScript, pos) source = script.pubkey_to_pubkeyhash(pubkey) valid_sig = redeemScript[ pos] == bitcoinlib.core.script.OP_CHECKSIGVERIFY pos += 1 if valid_sig: redeem_script_is_valid = redeemScript[pos + 1] == bitcoinlib.core.script.OP_DROP and \ redeemScript[pos + 2] == bitcoinlib.core.script.OP_DEPTH and \ redeemScript[pos + 3] == 0 and \ redeemScript[pos + 4] == bitcoinlib.core.script.OP_EQUAL except Exception as e: pass #traceback.print_exc() return pubkey, source, redeem_script_is_valid, found_data