def is_valid_contract_sig(self, contract, node_id=None): sig = contract[u"signature"][:] del contract[u"signature"] if sys.version_info >= (3, 0, 0): msg = str(contract).encode("ascii") else: msg = str(contract) # Use our address. msg = binascii.hexlify(msg).decode("utf-8") if node_id is None: address = self.wallet.get_address(self.wif) ret = self.wallet.verify_signature(address, sig, msg) else: # Use their node ID: try testnet. address = b2a_hashed_base58(b'o' + node_id) ret = self.wallet.verify_signature(address, sig, msg) if not ret: # Use their node ID: try mainnet. address = b2a_hashed_base58(b'\0' + node_id) ret = self.wallet.verify_signature(address, sig, msg) # Move sig back. contract[u"signature"] = sig[:] return ret
def render_address(script, testnet=True): # take a scriptPubKey (part of the TxOut) and convert into conventional human-readable # string... aka: the "payment address" from pycoin.encoding import b2a_hashed_base58 from pycoin.contrib.segwit_addr import encode as bech32_encode ll = len(script) if not testnet: bech32_hrp = 'bc' b58_addr = bytes([0]) b58_script = bytes([5]) else: bech32_hrp = 'tb' b58_addr = bytes([111]) b58_script = bytes([196]) # P2PKH if ll == 25 and script[0:3] == b'\x76\xA9\x14' and script[ 23:26] == b'\x88\xAC': return b2a_hashed_base58(b58_addr + script[3:3 + 20]) # P2SH if ll == 23 and script[0:2] == b'\xA9\x14' and script[22] == 0x87: return b2a_hashed_base58(b58_script + script[2:2 + 20]) # P2WPKH if ll == 22 and script[0:2] == b'\x00\x14': return bech32_encode(bech32_hrp, 0, script[2:]) # P2WSH if ll == 34 and script[0:2] == b'\x00\x20': return bech32_encode(bech32_hrp, 0, script[2:]) return '[script: %s]' % b2a_hex(script)
def fromPrivkey(cls, ecdsaPrivkey): """Returns a new Address object from the private key. The private key can be used to get the public key, hence the need only for the private key. """ rawPrivkey = cls.PRIVATE_KEY_PREFIX + ecdsaPrivkey.to_string() privkey = b2a_hashed_base58(rawPrivkey) ecdsaPubkey = ecdsaPrivkey.get_verifying_key() rawPubkey = cls.PUBLIC_KEY_PREFIX + hash160( "\x04" + ecdsaPubkey.to_string()) pubkey = b2a_hashed_base58(rawPubkey) return cls(pubkey, privkey)
def make_ms_address(M, keys, idx=0, is_change=0, addr_fmt=AF_P2SH, testnet=1, **make_redeem_args): # Construct addr and script need to represent a p2sh address import bech32 from pycoin.encoding import b2a_hashed_base58, hash160 if 'path_mapper' not in make_redeem_args: make_redeem_args['path_mapper'] = lambda cosigner: [HARD(45), cosigner, is_change, idx] script, pubkeys, xfp_paths = make_redeem(M, keys, **make_redeem_args) if addr_fmt == AF_P2WSH: hrp = ['bc', 'tb'][testnet] data = sha256(script).digest() addr = bech32.encode(hrp, 0, data) scriptPubKey = bytes([0x0, 0x20]) + data else: if addr_fmt == AF_P2SH: digest = hash160(script) elif addr_fmt == AF_P2WSH_P2SH: digest = hash160(b'\x00\x20' + sha256(script).digest()) else: raise ValueError(addr_fmt) prefix = bytes([196]) if testnet else bytes([5]) addr = b2a_hashed_base58(prefix + digest) scriptPubKey = bytes([0xa9, 0x14]) + digest + bytes([0x87]) return addr, scriptPubKey, script, zip(pubkeys, xfp_paths)
def get_data(self): """Get this object as a JSON/Storage compatible dict. Useful for storage and persistence. """ raw = self.prefix + to_bytes_32(self.rawPrivKey) return {"color_set": self.color_set.get_data(), "address_data": b2a_hashed_base58(raw)}
def get_data(self): """Get this object as a JSON/Storage compatible dict. Useful for storage and persistence. """ raw = self.prefix + to_bytes_32(self.rawPrivKey) return { "color_set": self.color_set.get_data(), "address_data": b2a_hashed_base58(raw) }
def slip132undo(orig): # take a SLIP-132 xpub/ypub/z/U/?pub/prv and convert into BIP-32 style # - preserve testnet vs. mainnet # - return addr fmt info from pycoin.encoding import a2b_hashed_base58, b2a_hashed_base58 from ckcc_protocol.constants import AF_P2WPKH_P2SH, AF_P2SH, AF_P2WSH, AF_P2WSH_P2SH from ckcc_protocol.constants import AF_P2WPKH assert orig[0] not in 'xt', "already legit bip32" xpub = a2b_hex('0488B21E') tpub = a2b_hex('043587cf') xprv = a2b_hex('0488ADE4') tprv = a2b_hex('04358394') variants = [ (False, AF_P2WPKH_P2SH, '049d7cb2', '049d7878', 'y'), (False, AF_P2WPKH, '04b24746', '04b2430c', 'z'), (False, AF_P2WSH_P2SH, '0295b43f', '0295b005', 'Y'), (False, AF_P2WSH, '02aa7ed3', '02aa7a99', 'Z'), (True, AF_P2WPKH_P2SH, '044a5262', '044a4e28', 'u'), (True, AF_P2WPKH, '045f1cf6', '045f18bc', 'v'), (True, AF_P2WSH_P2SH, '024289ef', '024285b5', 'U'), (True, AF_P2WSH, '02575483', '02575048', 'V'), ] raw = a2b_hashed_base58(orig) for testnet, addr_fmt, pub, priv, hint in variants: if raw[0:4] == a2b_hex(pub): return b2a_hashed_base58((tpub if testnet else xpub) + raw[4:]), \ testnet, addr_fmt, False if raw[0:4] == a2b_hex(priv): return b2a_hashed_base58((tprv if testnet else xprv) + raw[4:]), \ testnet, addr_fmt, True raise RuntimeError("unknown prefix")
def p2sh_address(key): """ Function to convert the given private key to the P2SH key used to signify a SegWit address starting with '3'. This SegWit address is a <redeemScript> (https://bitcoincore.org/en/segwit_wallet_dev/#creation-of-p2sh-p2wpkh-address). It starts with a OP_0, followed by a canonical push of the keyhash (i.e. 0x0014{20-byte keyhash}). """ return b2a_hashed_base58(b'\5' + hash160(b'\x00\x14' + hash160(key.sec(use_uncompressed=False))))
def scriptsig2adddr(scriptsig): if type(scriptsig) is not bytes: scriptsig = binascii.unhexlify(scriptsig) pos = 0 ln = scriptsig[pos] pos += 1 sig = sigscript[pos:pos + ln] pos += ln ln = scriptsig[pos] pos += 1 pubkey = scriptsig[pos:pos + ln:] pubkeyhash = encoding.hash160(pubkey) r = encoding.b2a_hashed_base58(settings.PUB_PREFIX + pubkeyhash) return r
def pkscript2addr(pkscript): if type(pkscript) is not bytes: pkscript = binascii.unhexlify(pkscript) # Pay-to-PubkeyHash if pkscript[:2] == b'\x76\xa9' and pkscript[-2:] == b'\x88\xac': ln = pkscript[2] pubkeyhash = pkscript[3:3 + ln] data = settings.PUB_PREFIX + pubkeyhash res = encoding.b2a_hashed_base58(data) return res # Pay-to-Script-Hash elif False: return 'TODO' # OP_RETURN elif pkscript[0] == b'\x6a': return 'null' return False
def address_for_pay_to_script_wit(script, netcode=None): if netcode is None: netcode = get_current_netcode() address_prefix = pay_to_script_wit_prefix_for_netcode(netcode) return encoding.b2a_hashed_base58(address_prefix + b'\0\0' + hashlib.sha256(script).digest())
def getJSONData(self): """Returns a dict that can later be plugged into the fromObj method for later retrieval of an Address. This is particularly useful for storing/retrieving from a data store.""" return {"pubkey": self.pubkey, "privkey": self.privkey} class TestnetAddress(Address): """TestnetAddress represents a Bitcoin Testnet address. Be sure that bitcoind is running with the "-testnet" flag. """ PUBLIC_KEY_PREFIX = "\x6F" PRIVATE_KEY_PREFIX = "\xEF" if __name__ == "__main__": # test the key generation test_key = 'a' * 32 address = Address.new(test_key) print address.pubkey rawPubkey = Address.PUBLIC_KEY_PREFIX + hash160( "\x04" + address.rawPubkey()) print b2a_hashed_base58(rawPubkey) assert address.privkey \ == "5JZB2s2RCtRUunKiqMbb6rAj3Z7TkJwa8zknL1cfTFpWoQArd6n", \ "address generation isn't what was expected" assert address.rawPrivkey() == test_key, "wrong priv key"
def rawPubkeyToAddress(cls, raw): return b2a_hashed_base58(cls.PUBLIC_KEY_PREFIX + raw)
def node_id_to_address(node_id): """Convert a node id to a bitcoin address.""" return b2a_hashed_base58(b'\0' + node_id)
def nodeid2address(hexnodeid): """Convert a node id to a bitcoin address.""" nodeid = binascii.unhexlify(hexnodeid) return b2a_hashed_base58(b'\0' + nodeid)
def do_test(as_text, as_bin): self.assertEqual(as_text, encoding.b2a_hashed_base58(as_bin)) self.assertEqual(as_bin, encoding.a2b_hashed_base58(as_text)) self.assertTrue(encoding.is_hashed_base58_valid(as_text)) bogus_text = as_text[:-1] + chr(1+ord(as_text[-1])) self.assertFalse(encoding.is_hashed_base58_valid(bogus_text))
def nodeid_to_address(nodeid): """Convert a node id to a bitcoin address.""" return b2a_hashed_base58(b'\0' + nodeid)
def pcode_b58(pcode): PREFIX = b'\x46' # Spec recommends b'\x23' return b2a_hashed_base58( PREFIX + pcode )
def btc_to_address(prefix, subkey): return b2a_hashed_base58(prefix + subkey.hash160())
def dump(psbt, hex_output, bin_output, testnet, base64, show_addrs): raw = psbt.read() if raw[0:10] == b'70736274ff': raw = _a2b_hex(raw.strip()) if raw[0:6] == b'cHNidP': raw = b64decode(raw) #assert raw[0:5] == b'psbt\xff' if hex_output: print(b2a_hex(raw)) sys.exit(0) if base64: print(str(b64encode(raw), 'ascii')) sys.exit(0) print("%d bytes in PSBT: %s" % (len(raw), psbt.name)) if bin_output: bin_output.write(raw) sys.exit(0) with io.BytesIO(raw) as fd: hdr = fd.read(4) sep1 = fd.read(1) print("-- HEADER --\n\n%s 0x%02x\n" % (str(hdr, 'ascii'), sep1[0])) print("-- GLOBALS --") num_ins = None num_outs = None section = 'globals' section_idx = 0 expect_outs = set() while 1: first = fd.read(1) if first == b'': print("-- ACTUAL EOF --") break try: ks = deser_compact_size(fd, first[0]) except: print("? confused at %d=0x%x" % (fd.tell(), fd.tell())) break if ks == 0: section_idx += 1 if section == 'globals': section_idx = 0 section = 'inputs' print("-- INPUT #0 --") elif section == 'inputs': if section_idx == num_ins: print("-- OUTPUT #0 --") section = 'outputs' section_idx = 0 else: print("-- INPUT #%d --" % section_idx) elif section == 'outputs': if section_idx == num_outs: print("-- EXPECT EOF --") section = 'past eof' section_idx = 0 else: print("-- OUTPUT #%d --" % section_idx) else: print("-- ?? %s ?? --" % section.upper()) continue try: assert ks key = fd.read(ks) vs = deser_compact_size(fd) assert vs val = fd.read(vs) except: print("? confused at %d=0x%x" % (fd.tell(), fd.tell())) break try: if section == 'globals': purpose = ['GLOBAL_UNSIGNED_TX', 'GLOBAL_XPUB'][key[0]] elif section == 'inputs': purpose = [ 'IN_NON_WITNESS_UTXO', 'IN_WITNESS_UTXO', 'IN_PARTIAL_SIG', 'IN_SIGHASH_TYPE', 'IN_REDEEM_SCRIPT', 'IN_WITNESS_SCRIPT', 'IN_BIP32_DERIVATION', 'IN_FINAL_SCRIPTSIG', 'IN_FINAL_SCRIPTWITNESS' ][key[0]] elif section == 'outputs': purpose = [ 'OUT_REDEEM_SCRIPT', 'OUT_WITNESS_SCRIPT', 'OUT_BIP32_DERIVATION' ][key[0]] except IndexError: purpose = 'Unknown type=0x%0x' % key[0] print('\n key: %02x ' % key[0], end='') if len(key) <= 1: print("(%s)" % purpose) else: print('%s\n (%s + %d bytes)' % (b2a_hex(key[1:]), purpose, ks - 1)) print('value: ', end='') if len(val) == 4 and key[0] != PSBT_GLOBAL_XPUB: nn, = struct.unpack("<I", val) print("'%s' = 0x%x = %d\n" % (b2a_hex(val), nn, nn)) continue print('%s (%d bytes)\n' % (b2a_hex(val), vs)) # prefix byte for addresses in current network ADP = b'\x6f' if testnet else b'\0' if (section, key[0]) in [('globals', PSBT_GLOBAL_UNSIGNED_TX), ('inputs', PSBT_IN_NON_WITNESS_UTXO)]: # Parse and sumarize the bitcoin transaction. # - also works for non-witness UTXO try: t = Tx.parse(io.BytesIO(val)) print(" Transaction: (%d inputs, %d outputs, %d witness)" % (len(t.txs_in), len(t.txs_out), sum(1 for i in t.txs_in if i.witness))) print(" : txid %s" % t.hash()) for n, i in enumerate(t.txs_in): print(" [in #%d] %s" % (n, i.address(ADP) if i.script else '(not signed)')) if section == 'globals': print(" from %s : %d" % (b2h_rev(i.previous_hash), i.previous_index)) for n, o in enumerate(t.txs_out): out_addr = render_address(o.script, testnet) print(" [out #%d] %.8f => %s" % (n, o.coin_value / 1E8, out_addr)) expect_outs.add(out_addr) print("\n") if num_ins is None: num_ins = len(t.txs_in) num_outs = len(t.txs_out) except: print("(unable to parse txn)") raise if (section, key[0]) == ('globals', PSBT_GLOBAL_XPUB): # key is: binary BIP32 serialization (not base58) # value is: master key fingerprint catenated with the derivation path of public key fingerprint = val[0:4] if len(val) > 4: path = [ struct.unpack_from('<I', val, offset=i)[0] for i in range(4, len(val), 4) ] path = [ str(i & 0x7fffffff) + ("'" if i & 0x80000000 else "") for i in path ] else: # valid: no subpath, just xfp. path = [] print(" XPUB: %s" % b2a_hashed_base58(key[1:])) print(" HD Path: (m=%s)/%s\n" % (xfp2hex(fingerprint), '/'.join(path))) if (section, key[0]) in [('inputs', PSBT_IN_BIP32_DERIVATION), ('outputs', PSBT_OUT_BIP32_DERIVATION)]: # HD key paths try: pubkey = key[1:] fingerprint = val[0:4] path = [ struct.unpack_from('<I', val, offset=i)[0] for i in range(4, len(val), 4) ] path = [ str(i & 0x7fffffff) + ("'" if i & 0x80000000 else "") for i in path ] # conservative: render them all, pick one found if expected # - but not helpful for multisig, need to look around to know if thats the case addrs = [] if show_addrs: if len(pubkey) in {33, 65}: # assume old skool b58 p2pkh, bitcoin mainnet, etc. h20 = hash160(pubkey) for prefix in [0, 111]: addrs.append( b2a_hashed_base58(bytes([prefix]) + h20)) for hrp in ['bc', 'tb']: addrs.append(bech32_encode(hrp, 0, h20)) # really? match = set(addrs).intersection(expect_outs) if match: addrs = list(match) print(" Pubkey: %s (%d bytes)" % (b2a_hex(pubkey), len(pubkey))) print(" HD Path: (m=%s)/%s" % (xfp2hex(fingerprint), '/'.join(path))) for addr in addrs: print(" = %s" % addr) print("\n") except: print("(unable to parse hdpath)") if (section, key[0]) in [('inputs', PSBT_IN_REDEEM_SCRIPT), ('inputs', PSBT_IN_WITNESS_SCRIPT), ('outputs', PSBT_OUT_REDEEM_SCRIPT), ('outputs', PSBT_OUT_WITNESS_SCRIPT)]: try: if val[-1] == 0xAE and len(val) > 22: M, N = (val[0] - 80, val[-2] - 80) print(" P2SH Multisig: %d of %d" % (M, N)) print(" Pubkeys: ") for idx in range(N): pk = val[1 + (34 * idx):] assert pk[0] == 0x21 print(" #%d: %s" % (idx + 1, b2a_hex(pk[1:1 + 33]))) exp = ((N * 34) + 3) if len(val) > exp: print(" (plus JUNK: %d bytes)" % (len(val) - exp)) print("\n") # XXX decode implied p2sh addresses here too? except: print("(unable to parse POSSIBLE multisig redeem script)")
def btc_to_private(exponent): return b2a_hashed_base58(b'\x80' + to_bytes_32(exponent) + b'\01')
print("\npycoin.key.Key example - ", my_netcode) #print("Private Key (dec): ", eval('0x' + privkey_hex)) print("Private Key (dec): ", int(privkey_hex, 16)) print("Private Key (hex): ", privkey_hex) privkey_bytes = unhexlify(privkey_hex) # use CBitcoinSecret to compress private key btc_secret = CBitcoinSecret.from_secret_bytes(privkey_bytes, True) print(" compressed: ", hexlify(btc_secret.to_bytes())) assert(btc_secret.is_compressed == True) assert(bitcoin.core.b2x(btc_secret.to_bytes()) == (privkey_hex + '01')) print("Private Key WIF: ", my_key.wif()) print(" uncompressed: ", my_key.wif(use_uncompressed=True)) print("Privkey hashed base58: ", encoding.b2a_hashed_base58(privkey_bytes)) print() ## Public key and address public_key = my_key.public_pair() (public_key_x, public_key_y) = public_key print("Public Key Pair: ", public_key) print(" x as hex: ", hex(public_key[0])) print(" y as hex: ", hex(public_key[1])) #compressed_indicator_1 = '02' if (public_key_y % 2) == 0 else '03' compressed_indicator = True if (public_key_y % 2) == 0 else False print("Public key y parity: ", 'even' if compressed_indicator else 'odd') assert(compressed_indicator != my_key._use_uncompressed)
def do_test(as_text, as_bin): self.assertEqual(as_text, encoding.b2a_hashed_base58(as_bin)) self.assertEqual(as_bin, encoding.a2b_hashed_base58(as_text)) self.assertTrue(encoding.is_hashed_base58_valid(as_text)) bogus_text = as_text[:-1] + chr(1 + ord(as_text[-1])) self.assertFalse(encoding.is_hashed_base58_valid(bogus_text))