def pycoin_sec2addr(sec): coin = ci.external_tests['testnet']['pycoin'][g.coin] if g.testnet else g.coin key = pcku.parse_key(sec,[network_for_netcode(coin)],secp256k1_generator)[1] if key is None: die(1,"can't parse {}".format(sec)) o = pcku.create_output(sec,key,network_for_netcode(coin))[0] suf = ('_uncompressed','')[addr_type.compressed] wif = o['wif{}'.format(suf)] addr = o['p2sh_segwit' if addr_type.name == 'segwit' else '{}_address{}'.format(coin,suf)] return wif,addr
def pycoin_sec2addr(sec): coin = ci.external_tests['testnet']['pycoin'][g.coin] if g.testnet else g.coin key = pcku.parse_key(sec,[network_for_netcode(coin)])[1] if key is None: die(1,"can't parse {}".format(sec)) d = { 'legacy': ('wif_uncompressed','address_uncompressed'), 'compressed': ('wif','address'), 'segwit': ('wif','p2sh_segwit'), }[addr_type.name] return [pcku.create_output(sec,key,network_for_netcode(coin),d[i])[0][d[i]] for i in (0,1)]
def ku(args, parser): fallback_network = network_for_netcode(args.network or get_current_netcode()) parse_networks = [fallback_network] + [ network_for_netcode(netcode) for netcode in network_codes() ] if args.network: parse_networks = [network_for_netcode(args.network)] override_network = None if args.override_network: # Override the network value, so we can take the same xpubkey and view what # the values would be on each other network type. override_network = network_for_netcode(args.override_network) def parse_stdin(): return [ item for item in sys.stdin.readline().strip().split(' ') if len(item) > 0 ] output_key_set = set(args.brief or []) if args.wallet: output_key_set.add("wallet_key") elif args.wif: output_key_set.add("wif_uncompressed" if args.uncompressed else "wif") elif args.address: output_key_set.add("address" + ("_uncompressed" if args.uncompressed else "")) items = args.item if len(args.item) > 0 else parse_stdin() for item in items: key = parse_key(item, parse_networks) if key is None: print("can't parse %s" % item, file=sys.stderr) continue if override_network: key = key.override_network(override_network) display_network = override_network or key._network or fallback_network if hasattr(key, "subkeys"): key_iter = key.subkeys(args.subkey) else: key_iter = [key] for key in key_iter: if args.public: key = key.public_copy() output_dict, output_order = create_output(item, key, output_key_set) generate_output(args, output_dict, output_order)
def pycoin_sec2addr(sec): coin = ci.external_tests['testnet']['pycoin'][ g.coin] if g.testnet else g.coin key = pcku.parse_key(sec, [network_for_netcode(coin)])[1] if key is None: die(1, "can't parse {}".format(sec)) d = { 'legacy': ('wif_uncompressed', 'address_uncompressed'), 'compressed': ('wif', 'address'), 'segwit': ('wif', 'p2sh_segwit'), }[addr_type.name] return [ pcku.create_output(sec, key, network_for_netcode(coin), d[i])[0][d[i]] for i in (0, 1) ]
def keychain(args, parser): network = network_for_netcode(args.netcode) parse = network.ui.parse keychain = Keychain(sqlite3.connect(args.keychain)) keys = [] for _ in args.key: key = parse(_, types=["electrum", "bip32"]) if not key: raise ValueError("can't parse %s" % _) keys.append(key) subkey_paths = args.subkey_paths m = args.multisig if m and m > len(keys): raise ValueError("not enough keys for %d signatures" % m) total_paths = 0 script_for_multisig = network.ui._script_info.script_for_multisig for path in subpaths_for_path_range(subkey_paths): if m: secs = sorted([_.subkey_for_path(path).sec() for _ in keys]) script = script_for_multisig(m, secs) keychain.add_p2s_script(script) print(network.ui.address_for_p2s(script)) total_paths += keychain.add_keys_path(keys, path) keychain.commit() print("%d total paths" % total_paths, file=sys.stderr)
def test_is_wif_valid(self): WIFS = [ "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf", "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU74NMTptX4", "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAvUcVfH" ] for wif in WIFS: self.assertEqual(is_wif_valid(wif), "BTC") a = wif[:-1] + chr(ord(wif[-1]) + 1) self.assertEqual(is_wif_valid(a), None) from pycoin.networks.registry import network_for_netcode NETWORK_NAMES = network_codes() for netcode in NETWORK_NAMES: network = network_for_netcode(netcode) if not getattr(network, "key", None): continue for se in range(1, 10): key = network.key(secret_exponent=se, generator=secp256k1_generator) for tv in [True, False]: wif = key.wif(use_uncompressed=tv) self.assertEqual( is_wif_valid(wif, allowable_netcodes=[netcode]), netcode) a = wif[:-1] + chr(ord(wif[-1]) + 1) self.assertEqual( is_wif_valid(a, allowable_netcodes=[netcode]), None)
def create_parser(): codes = network_codes() parser = argparse.ArgumentParser( description=( 'Cache look-up information into a Keychain for use with tx. ' 'Useful for hiearchical keys with many children.'), epilog=('Known networks codes:\n ' + ', '.join([ '%s (%s)' % (i, network_for_netcode(i).full_name()) for i in codes ]))) parser.add_argument('-n', "--netcode", help='specify network by netcode', choices=codes, default="BTC") parser.add_argument( '-m', "--multisig", metavar="sigcount", type=int, help='multisig, with this many signatures need to unencumber the funds' ) parser.add_argument('keychain', help='the keychain file (SQLite3 formatted)') parser.add_argument('subkey_paths', help='subkey paths (example: 0H/2/15-20)') parser.add_argument( 'key', nargs="+", help='a hierarchical wallet key string (public suffices)') return parser
def keychain(args, parser): network = network_for_netcode(args.netcode) parse = network.ui.parse keychain = network.keychain(sqlite3.connect(args.keychain)) keys = [] for _ in args.key: key = parse(_, types=["electrum", "bip32"]) if not key: raise ValueError("can't parse %s" % _) keys.append(key) subkey_paths = args.subkey_paths m = args.multisig if m and m > len(keys): raise ValueError("not enough keys for %d signatures" % m) total_paths = 0 for path in subpaths_for_path_range(subkey_paths): if m: secs = sorted([_.subkey_for_path(path).sec() for _ in keys]) script = network.contract.for_multisig(m, secs) keychain.add_p2s_script(script) print(network.ui.address_for_p2s(script)) total_paths += keychain.add_keys_path(keys, path) keychain.commit() print("%d total paths" % total_paths, file=sys.stderr)
def create_parser(): codes = network_codes() parser = argparse.ArgumentParser( description='Create or verify a text signature using bitcoin standards', epilog=('Known networks codes:\n ' + ', '.join([ '%s (%s)' % (i, network_for_netcode(i).full_name()) for i in codes ]))) parser.add_argument('-n', "--network", help='specify network (default: BTC = Bitcoin)', default='BTC', choices=codes) subparsers = parser.add_subparsers(dest="command") sign = subparsers.add_parser('sign', help='sign a message with a private key') sign.add_argument('WIF', help='the WIF to sign the message with') add_read_msg_arguments(sign, "signed") verify = subparsers.add_parser('verify') verify.add_argument('signature', help='the signature to verify') verify.add_argument('address', nargs="?", help='the address to verify against') add_read_msg_arguments(verify, "verified") return parser
def test_is_wif_valid(self): WIFS = [ "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf", "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU74NMTptX4", "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAvUcVfH" ] for wif in WIFS: self.assertEqual(BTC.parse.wif(wif).wif(), wif) a = wif[:-1] + chr(ord(wif[-1]) + 1) self.assertIsNone(BTC.parse.wif(a)) NETWORK_NAMES = network_codes() for netcode in NETWORK_NAMES: network = network_for_netcode(netcode) if not getattr(network, "Key", None): continue for se in range(1, 10): key = network.Key(secret_exponent=se) for tv in [True, False]: wif = key.wif(is_compressed=tv) self.assertEqual(network.parse.wif(wif).wif(), wif) a = wif[:-1] + chr(ord(wif[-1]) + 1) self.assertIsNone(network.parse.wif(a))
def parse_context(args, parser): network = network_for_netcode(args.network) tx_class = network.tx # we create the tx_db lazily tx_db = None if args.db: try: txs = [tx_class.from_hex(tx_hex) for tx_hex in args.db] except Exception: parser.error("can't parse ") the_ram_tx_db = dict((tx.hash(), tx) for tx in txs) if tx_db is None: tx_db = create_tx_db(network) tx_db.lookup_methods.append(the_ram_tx_db.get) # defaults txs = [] spendables = [] payables = [] key_iters = [] # there are a few warnings we might optionally print out, but only if # they are relevant. We don't want to print them out multiple times, so we # collect them here and print them at the end if they ever kick in. warning_spendables = None for arg in args.argument: tx, tx_db = parse_tx(tx_class, arg, parser, tx_db, network) if tx: txs.append(tx) continue if key_found(arg, payables, key_iters, network): continue if parse_parts(tx_class, arg, spendables, payables, network): continue payable = script_for_address_or_opcodes(network, arg) if payable is not None: payables.append((payable, 0)) continue parser.error("can't parse %s" % arg) parse_private_key_file(args, key_iters) if args.fetch_spendables: warning_spendables = message_about_spendables_for_address_env(args.network) for address in args.fetch_spendables: spendables.extend(spendables_for_address(address, args.network)) return (network, txs, spendables, payables, key_iters, tx_db, warning_spendables)
def coinc(args, parser): network = network_for_netcode(args.network) for arg in args.argument: info = info_for_arg(arg, network) for k in ("compiled_script_hex address_p2s preimage_p2s_hex " "address_p2s_wit underlying_script disassembled_script" ).split(): print(info[k])
def msg_sign(args, parser): network = network_for_netcode(args.network) message_signer = network.msg message_hash = get_message_hash(args, message_signer) network, key = parse_key(args.WIF, [network]) is_compressed = key.is_compressed() sig = message_signer.signature_for_message_hash( key.secret_exponent(), msg_hash=message_hash, is_compressed=is_compressed) print(sig)
def ku(args, parser): fallback_network = network_for_netcode(args.network or get_current_netcode()) parse_networks = [fallback_network] + [network_for_netcode(netcode) for netcode in network_codes()] if args.network: parse_networks = [network_for_netcode(args.network)] override_network = None if args.override_network: # Override the network value, so we can take the same xpubkey and view what # the values would be on each other network type. override_network = network_for_netcode(args.override_network) def parse_stdin(): return [item for item in sys.stdin.readline().strip().split(' ') if len(item) > 0] output_key_set = set(args.brief or []) if args.wallet: output_key_set.add("wallet_key") elif args.wif: output_key_set.add("wif_uncompressed" if args.uncompressed else "wif") elif args.address: output_key_set.add("address" + ("_uncompressed" if args.uncompressed else "")) items = args.item if len(args.item) > 0 else parse_stdin() for item in items: key_network, key = parse_key(item, parse_networks) if key is None: print("can't parse %s" % item, file=sys.stderr) continue display_network = override_network or key_network or fallback_network if hasattr(key, "subkeys"): key_iter = key.subkeys(args.subkey) else: key_iter = [key] for key in key_iter: if args.public: key = key.public_copy() output_dict, output_order = create_output(item, key, display_network, output_key_set) generate_output(args, output_dict, output_order)
def mnemonic_to_bip32_node(mnemonic, passphrase='', net_code='BTC'): """ mnemonic sentence to bip32 node :param mnemonic: mnemonic sentence :param passphrase: used for PBKDF2 salt('mnemonic' + passphrase) :param net_code: 'BTC' => "mainnet", 'XTN' => "testnet3" """ master_seed = Mnemonic.to_seed(mnemonic, passphrase=passphrase) network = network_for_netcode(net_code) return network.keys.bip32_seed(master_seed)
def external_key_from_account_hwif(hwif, key_idx=0, net_code='BTC'): """ path 0 / {key_idx} :param hwif: bip32 private key format :param key_idx: 0 as first key :param net_code: hwif corresponding net code """ network = network_for_netcode(net_code) node = network.parse.bip32(hwif) return node.subkey_for_path(f'0/{key_idx}')
def mnemonic_to_bip32_hwif(mnemonic, passphrase='', net_code='BTC'): """ mnemonic sentence to bip32 private key format which starts with 'xprv' :param mnemonic: mnemonic sentence :param passphrase: used for PBKDF2 salt('mnemonic' + passphrase) :param net_code: BTC or XTN(test net) """ master_seed = Mnemonic.to_seed(mnemonic, passphrase=passphrase) network = network_for_netcode(net_code) master = network.keys.bip32_seed(master_seed) return master.hwif(as_private=True)
def ku(args, parser): generator = secp256k1_generator fallback_network = network_for_netcode(args.network or get_current_netcode()) parse_networks = [ network_for_netcode(netcode) for netcode in network_codes() ] if args.network: parse_networks = [network_for_netcode(args.network)] override_network = None if args.override_network: # Override the network value, so we can take the same xpubkey and view what # the values would be on each other network type. override_network = network_for_netcode(args.override_network) def parse_stdin(): return [ item for item in sys.stdin.readline().strip().split(' ') if len(item) > 0 ] items = args.item if len(args.item) > 0 else parse_stdin() for item in items: key_network, key = parse_key(item, parse_networks, generator) if key is None: print("can't parse %s" % item, file=sys.stderr) continue display_network = override_network or key_network or fallback_network for key in key.subkeys(args.subkey or ""): if args.public: key = key.public_copy() output_dict, output_order = create_output(item, key, display_network) generate_output(args, output_dict, output_order)
def bip44_btc_account(mnemonic, account=0, passphrase=''): """ bip44 btc format m / 44' / 0' / {account}' account can generate related address/key pairs :param mnemonic: mnemonic sentence :param account: 0 as first account :param passphrase: used for PBKDF2 salt('mnemonic' + passphrase) """ master_seed = Mnemonic.to_seed(mnemonic, passphrase=passphrase) network = network_for_netcode('BTC') master = network.keys.bip32_seed(master_seed) return master.subkey_for_path(f'44H/0H/{account}H')
def msg_sign(args, parser): network = network_for_netcode(args.network) message_signer = MessageSigner(network.network_name, network.ui, secp256k1_generator) message_hash = get_message_hash(args, message_signer) network, key = parse_key(args.WIF, [network], secp256k1_generator) is_compressed = not key._use_uncompressed() sig = message_signer.signature_for_message_hash( key.secret_exponent(), msg_hash=message_hash, is_compressed=is_compressed) print(sig)
def bip44_test_external_key(mnemonic, account=0, key_idx=0, passphrase=''): """ bip44 testnet format m / 44' / 1' / {account}' / 0 / {key_idx} :param mnemonic: mnemonic sentence :param account: 0 as first account :param key_idx: 0 as first key :param passphrase: used for PBKDF2 salt('mnemonic' + passphrase) """ master_seed = Mnemonic.to_seed(mnemonic, passphrase=passphrase) network = network_for_netcode('XTN') master = network.keys.bip32_seed(master_seed) return master.subkey_for_path(f'44H/1H/{account}H/0/{key_idx}')
def bip44_eth_account(mnemonic, account=0, passphrase=''): """ bip44 eth format m / 44' / 0' / {account}' account can generate related address/key pairs :param mnemonic: mnemonic sentence :param account: 0 as first account :param passphrase: used for PBKDF2 salt('mnemonic' + passphrase) """ master_seed = Mnemonic.to_seed(mnemonic, passphrase=passphrase) # we just need the private key, BTC symbol will not used to generate address for ETH network = network_for_netcode('BTC') master = network.keys.bip32_seed(master_seed) return master.subkey_for_path(f'44H/60H/{account}H')
def create_parser(): codes = network_codes() parser = argparse.ArgumentParser( description=( 'Cache look-up information into a Keychain for use with tx. ' 'Useful for hiearchical keys with many children.'), epilog=('Known networks codes:\n ' + ', '.join(['%s (%s)' % (i, network_for_netcode(i).full_name()) for i in codes])) ) parser.add_argument('-n', "--netcode", help='specify network by netcode', choices=codes, default="BTC") parser.add_argument('-m', "--multisig", metavar="sigcount", type=int, help='multisig, with this many signatures need to unencumber the funds') parser.add_argument('keychain', help='the keychain file (SQLite3 formatted)') parser.add_argument('subkey_paths', help='subkey paths (example: 0H/2/15-20)') parser.add_argument('key', nargs="+", help='a hierarchical wallet key string (public suffices)') return parser
def test_keychain(self): netcode = "BTC" network = network_for_netcode(netcode) BIP32 = network.ui._bip32node_class keychain = Keychain() bip32_list = [BIP32.from_master_secret(_) for _ in [b"foo", b"bar"]] for bip32 in bip32_list: keychain.add_key_paths(bip32.public_copy(), subpaths_for_path_range("0-1/0-10")) keychain.add_secrets(bip32_list) for bip32 in bip32_list: for path in ["0/5", "1/2", "0/9"]: subkey = bip32.subkey_for_path("0/5") v = keychain.get(subkey.hash160()) self.assertEqual(v[0], subkey.secret_exponent()) v = keychain.get(b'0' * 32) self.assertEqual(v, None)
def test_is_public_private_bip32_valid(self): from pycoin.networks.registry import network_for_netcode NETWORK_NAMES = network_codes() WALLET_KEYS = ["foo", "1", "2", "3", "4", "5"] # not all networks support BIP32 yet for netcode in "BTC XTN DOGE".split(): network = network_for_netcode(netcode) BIP32Node = network.ui._bip32node_class for wk in WALLET_KEYS: wallet = BIP32Node.from_master_secret(secp256k1_generator, wk.encode("utf8")) text = wallet.wallet_key(as_private=True) self.assertEqual( is_private_bip32_valid(text, allowable_netcodes=NETWORK_NAMES), netcode) self.assertEqual( is_public_bip32_valid(text, allowable_netcodes=NETWORK_NAMES), None) a = text[:-1] + chr(ord(text[-1]) + 1) self.assertEqual( is_private_bip32_valid(a, allowable_netcodes=NETWORK_NAMES), None) self.assertEqual( is_public_bip32_valid(a, allowable_netcodes=NETWORK_NAMES), None) text = wallet.wallet_key(as_private=False) self.assertEqual( is_private_bip32_valid(text, allowable_netcodes=NETWORK_NAMES), None) self.assertEqual( is_public_bip32_valid(text, allowable_netcodes=NETWORK_NAMES), netcode) a = text[:-1] + chr(ord(text[-1]) + 1) self.assertEqual( is_private_bip32_valid(a, allowable_netcodes=NETWORK_NAMES), None) self.assertEqual( is_public_bip32_valid(a, allowable_netcodes=NETWORK_NAMES), None)
def test_repr(self): BitcoinTestnet = network_for_netcode("XTN") Key = BitcoinTestnet.ui._key_class key = Key(secret_exponent=273) wallet = XTNBIP32Node.from_master_secret( bytes(key.wif().encode('ascii'))) address = wallet.address() pub_k = key_from_text(address, networks=[BitcoinTestnet]) self.assertEqual(repr(pub_k), '<myb5gZNXePNf2E2ksrjnHRFCwyuvt7oEay>') wif = wallet.wif() priv_k = key_from_text(wif, networks=[BitcoinTestnet]) self.assertEqual( repr(priv_k), 'private_for <XTNSEC:03ad094b1dc9fdce5d3648ca359b4e210a89d049532fdd39d9ccdd8ca393ac82f4>' )
def coinc(args, parser): network = network_for_netcode(args.network) script_tools = network.extras.ScriptTools for arg in args.argument: compiled_script = script_tools.compile(arg) print(b2h(compiled_script)) address_p2s = network.ui.address_for_p2s(compiled_script) print(address_p2s) print(b2h(network.ui.script_for_address(address_p2s))) address_p2s_wit = network.ui.address_for_p2s_wit(compiled_script) print(address_p2s_wit) print(b2h(network.ui.script_for_address(address_p2s_wit))) print(script_tools.disassemble(compiled_script))
def msg_verify(args, parser): network = network_for_netcode(args.network) message_signer = network.msg message_hash = get_message_hash(args, message_signer) try: pair, is_compressed = message_signer.pair_for_message_hash(args.signature, msg_hash=message_hash) except EncodingError: pass ta = network.address.for_p2pkh(public_pair_to_hash160_sec(pair, compressed=is_compressed)) if args.address: if ta == args.address: print("signature ok") return 0 else: print("bad signature, matches %s" % ta) return 1 else: print(ta)
def make_tests_for_netcode(netcode): network = network_for_netcode(netcode) class KuTest(ToolTest): @classmethod def setUpClass(cls): cls.parser = ku.create_parser() cls.tool_name = "ku" def test_ku_create(self): output = self.launch_tool("ku create -w -n %s" % netcode).split("\n") bip32 = network.parse.bip32_prv(output[0]) bip32_as_text = bip32.hwif(as_private=True) self.assertEqual(output[0], bip32_as_text) return KuTest
def msg_verify(args, parser): network = network_for_netcode(args.network) message_signer = network.msg message_hash = get_message_hash(args, message_signer) try: pair, is_compressed = message_signer.pair_for_message_hash( args.signature, msg_hash=message_hash) except EncodingError: pass ta = network.address.for_p2pkh( public_pair_to_hash160_sec(pair, compressed=is_compressed)) if args.address: if ta == args.address: print("signature ok") return 0 else: print("bad signature, matches %s" % ta) return 1 else: print(ta)
def test_is_public_private_bip32_valid(self): from pycoin.networks.registry import network_for_netcode WALLET_KEYS = ["foo", "1", "2", "3", "4", "5"] # not all networks support BIP32 yet for netcode in NETCODES: network = network_for_netcode(netcode) for wk in WALLET_KEYS: wallet = network.keys.bip32_seed(wk.encode("utf8")) text = wallet.hwif(as_private=True) self.assertEqual(network.parse.bip32_prv(text).hwif(as_private=True), text) self.assertIsNone(network.parse.bip32_pub(text)) a = text[:-1] + chr(ord(text[-1])+1) self.assertIsNone(network.parse.bip32_prv(a)) self.assertIsNone(network.parse.bip32_pub(a)) text = wallet.hwif(as_private=False) self.assertIsNone(network.parse.bip32_prv(text)) self.assertEqual(network.parse.bip32_pub(text).hwif(), text) a = text[:-1] + chr(ord(text[-1])+1) self.assertIsNone(network.parse.bip32_prv(a)) self.assertIsNone(network.parse.bip32_pub(a))
def create_parser(): codes = network_codes() EPILOG = ('Known networks codes:\n ' + ', '.join( ['%s (%s)' % (i, network_for_netcode(i).full_name()) for i in codes])) parser = argparse.ArgumentParser( description="Compile or disassemble scripts.", epilog=EPILOG) parser.add_argument( '-n', "--network", default=get_current_netcode(), choices=codes, help=('Network code (environment variable PYCOIN_DEFAULT_NETCODE ' 'or "BTC"=Bitcoin mainnet if unset)')) parser.add_argument("argument", nargs="+", help='script to compile. To dump hex, prefix with 0x') return parser
def test_is_public_private_bip32_valid(self): from pycoin.networks.registry import network_for_netcode WALLET_KEYS = ["foo", "1", "2", "3", "4", "5"] # not all networks support BIP32 yet for netcode in NETCODES: network = network_for_netcode(netcode) for wk in WALLET_KEYS: wallet = network.keys.bip32_seed(wk.encode("utf8")) text = wallet.hwif(as_private=True) self.assertEqual( network.parse.bip32_prv(text).hwif(as_private=True), text) self.assertIsNone(network.parse.bip32_pub(text)) a = text[:-1] + chr(ord(text[-1]) + 1) self.assertIsNone(network.parse.bip32_prv(a)) self.assertIsNone(network.parse.bip32_pub(a)) text = wallet.hwif(as_private=False) self.assertIsNone(network.parse.bip32_prv(text)) self.assertEqual(network.parse.bip32_pub(text).hwif(), text) a = text[:-1] + chr(ord(text[-1]) + 1) self.assertIsNone(network.parse.bip32_prv(a)) self.assertIsNone(network.parse.bip32_pub(a))
def test_is_public_private_bip32_valid(self): from pycoin.networks.registry import network_for_netcode WALLET_KEYS = ["foo", "1", "2", "3", "4", "5"] # not all networks support BIP32 yet for netcode in NETCODES: network = network_for_netcode(netcode) BIP32Node = network.ui._bip32node_class for wk in WALLET_KEYS: wallet = BIP32Node.from_master_secret(wk.encode("utf8")) text = wallet.hwif(as_private=True) self.assertEqual(is_private_bip32_valid(text, allowable_netcodes=NETCODES), netcode) self.assertEqual(is_public_bip32_valid(text, allowable_netcodes=NETCODES), None) a = text[:-1] + chr(ord(text[-1])+1) self.assertEqual(is_private_bip32_valid(a, allowable_netcodes=NETCODES), None) self.assertEqual(is_public_bip32_valid(a, allowable_netcodes=NETCODES), None) text = wallet.hwif(as_private=False) self.assertEqual(is_private_bip32_valid(text, allowable_netcodes=NETCODES), None) self.assertEqual(is_public_bip32_valid(text, allowable_netcodes=NETCODES), netcode) a = text[:-1] + chr(ord(text[-1])+1) self.assertEqual(is_private_bip32_valid(a, allowable_netcodes=NETCODES), None) self.assertEqual(is_public_bip32_valid(a, allowable_netcodes=NETCODES), None)
def create_parser(): codes = network_codes() parser = argparse.ArgumentParser( description='Create or verify a text signature using bitcoin standards', epilog=('Known networks codes:\n ' + ', '.join(['%s (%s)' % (i, network_for_netcode(i).full_name()) for i in codes])) ) parser.add_argument('-n', "--network", help='specify network (default: BTC = Bitcoin)', default='BTC', choices=codes) subparsers = parser.add_subparsers(dest="command") sign = subparsers.add_parser('sign', help='sign a message with a private key') sign.add_argument('WIF', help='the WIF to sign the message with') add_read_msg_arguments(sign, "signed") verify = subparsers.add_parser('verify') verify.add_argument('signature', help='the signature to verify') verify.add_argument('address', nargs="?", help='the address to verify against') add_read_msg_arguments(verify, "verified") return parser
def create_parser(): codes = network_codes() parser = argparse.ArgumentParser( description='Crypto coin utility ku ("key utility") to show' ' information about Bitcoin or other cryptocoin data structures.', epilog=('Known networks codes:\n ' + ', '.join(['%s (%s)' % (i, network_for_netcode(i).full_name()) for i in codes])) ) parser.add_argument('-w', "--wallet", help='show just Bitcoin wallet key', action='store_true') parser.add_argument('-W', "--wif", help='show just Bitcoin WIF', action='store_true') parser.add_argument('-a', "--address", help='show just Bitcoin address', action='store_true') parser.add_argument( '-u', "--uncompressed", help='show output in uncompressed form', action='store_true') parser.add_argument( '-P', "--public", help='only show public version of wallet keys', action='store_true') parser.add_argument('-j', "--json", help='output as JSON', action='store_true') parser.add_argument('-b', "--brief", nargs="*", help='brief output; display a single field') parser.add_argument('-s', "--subkey", help='subkey path (example: 0H/2/15-20)', default="") parser.add_argument('-n', "--network", help='specify network', choices=codes) parser.add_argument( "--override-network", help='override detected network type', default=None, choices=codes) parser.add_argument( 'item', nargs="*", help='a BIP0032 wallet key string;' ' a WIF;' ' a bitcoin address;' ' an SEC (ie. a 66 hex chars starting with 02, 03 or a 130 hex chars starting with 04);' ' the literal string "create" to create a new wallet key using strong entropy sources;' ' P:wallet passphrase (NOT RECOMMENDED);' ' H:wallet passphrase in hex (NOT RECOMMENDED);' ' E:electrum value (either a master public, master private, or initial data);' ' secret_exponent (in decimal or hex);' ' x,y where x,y form a public pair (y is a number or one of the strings "even" or "odd");' ' hash160 (as 40 hex characters).' ' If this argument is missing, input data will be read from stdin.') return parser
def test_is_public_private_bip32_valid(self): from pycoin.networks.registry import network_for_netcode WALLET_KEYS = ["foo", "1", "2", "3", "4", "5"] # not all networks support BIP32 yet for netcode in NETCODES: network = network_for_netcode(netcode) BIP32Node = network.ui._bip32node_class for wk in WALLET_KEYS: wallet = BIP32Node.from_master_secret(wk.encode("utf8")) text = wallet.hwif(as_private=True) self.assertEqual( is_private_bip32_valid(text, allowable_netcodes=NETCODES), netcode) self.assertEqual( is_public_bip32_valid(text, allowable_netcodes=NETCODES), None) a = text[:-1] + chr(ord(text[-1]) + 1) self.assertEqual( is_private_bip32_valid(a, allowable_netcodes=NETCODES), None) self.assertEqual( is_public_bip32_valid(a, allowable_netcodes=NETCODES), None) text = wallet.hwif(as_private=False) self.assertEqual( is_private_bip32_valid(text, allowable_netcodes=NETCODES), None) self.assertEqual( is_public_bip32_valid(text, allowable_netcodes=NETCODES), netcode) a = text[:-1] + chr(ord(text[-1]) + 1) self.assertEqual( is_private_bip32_valid(a, allowable_netcodes=NETCODES), None) self.assertEqual( is_public_bip32_valid(a, allowable_netcodes=NETCODES), None)
def test_is_wif_valid(self): WIFS = ["KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf", "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU74NMTptX4", "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAvUcVfH"] for wif in WIFS: self.assertEqual(BTC.parse.wif(wif).wif(), wif) a = wif[:-1] + chr(ord(wif[-1])+1) self.assertIsNone(BTC.parse.wif(a)) NETWORK_NAMES = network_codes() for netcode in NETWORK_NAMES: network = network_for_netcode(netcode) if not getattr(network, "Key", None): continue for se in range(1, 10): key = network.Key(secret_exponent=se) for tv in [True, False]: wif = key.wif(is_compressed=tv) self.assertEqual(network.parse.wif(wif).wif(), wif) a = wif[:-1] + chr(ord(wif[-1])+1) self.assertIsNone(network.parse.wif(a))
def _manually_initialize(self): """ Create words (if is None) and start seed and master node Then we generate the first addresses, so we can check if we already have transactions """ self.mnemonic = Mnemonic(self.language) if not self.words: # Initialized but still locked return # Validate words first self.validate_words() assert isinstance(self.passphrase, bytes), 'Passphrase must be in bytes' # Master seed seed = self.mnemonic.to_seed(self.words, self.passphrase.decode('utf-8')) # Master node from pycoin.networks.registry import network_for_netcode _register_pycoin_networks() network = network_for_netcode('htr') key = network.keys.bip32_seed(seed) # Until account key should be hardened # Chain path = 44'/0'/0'/0 # 44' (hardened) -> BIP44 # 280' (hardened) -> Coin type (280 = hathor) # 0' (hardened) -> Account # 0 -> Chain self.chain_key = key.subkey_for_path('44H/280H/0H/0') for key in self.chain_key.children(self.initial_key_generation, 0, False): self._key_generated(key, key.child_index())
def test_is_wif_valid(self): WIFS = ["KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf", "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU74NMTptX4", "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAvUcVfH"] for wif in WIFS: self.assertEqual(is_wif_valid(wif, allowable_netcodes=NETCODES), "BTC") a = wif[:-1] + chr(ord(wif[-1])+1) self.assertEqual(is_wif_valid(a), None) from pycoin.networks.registry import network_for_netcode NETWORK_NAMES = network_codes() for netcode in NETWORK_NAMES: network = network_for_netcode(netcode) if not getattr(network, "key", None): continue for se in range(1, 10): key = network.key(secret_exponent=se) for tv in [True, False]: wif = key.wif(use_uncompressed=tv) self.assertEqual(is_wif_valid(wif, allowable_netcodes=[netcode]), netcode) a = wif[:-1] + chr(ord(wif[-1])+1) self.assertEqual(is_wif_valid(a, allowable_netcodes=[netcode]), None)
valid_private_key = False while not valid_private_key: my_secret = 1 #util.randrange(ecdsa.generator_secp256k1.order()) valid_private_key = 0 < my_secret < ecdsa.generator_secp256k1.order() print("") my_prng = util.PRNG(util.randrange(ecdsa.generator_secp256k1.order())) print("PRNG (random generator) 32 bytes: ", b2h(my_prng.__call__(32))) my_netcode = "BTC" # mainnet: BTC, testnet3: XTN my_key = Key(secret_exponent=my_secret, is_compressed=True, netcode=my_netcode) ## netcode list: pycoin.networks.all.py pp = pprint.PrettyPrinter(indent=2) my_network = registry.network_for_netcode(my_netcode) my_addr_prefix = registry._lookup(my_netcode, "address") getattr(my_network, "address") pp.pprint(my_network.__dict__) pprint.pprint(my_network.__dict__.keys(), width=60, depth=2) privkey_hex = b2h(encoding.to_bytes_32(my_key.secret_exponent())) assert(len(privkey_hex) == 64) 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
def make_tests_for_netcode(netcode): network = network_for_netcode(netcode) Tx = network.tx annotate_scripts = network.annotate.annotate_scripts class DisassembleTest(unittest.TestCase): def test_validate(self): input_tx = Tx.from_hex( "01000000019c97afdf6c9a31ffa86d71ea79a079001e2b59ee408fd418498219400639ac0a01" "0000008b4830450220363cffae09599397b21e6d8a8073fb1dfbe06b6acdd0f2f7d3fea86ca9" "c3f605022100fa255a6ed23fd825c759ef1a885a31cad0989606ca8a3a16657d50fe3cef5828" "014104ff444bac08308b9ec97f56a652ad8866e0ba804da97868909999566cb377f4a2c8f100" "0e83b496868f3a282e1a34df78565b65c15c3fa21a0763fd81a3dfbbb6ffffffff02c05eecde" "010000001976a914588554e6cc64e7343d77117da7e01357a6111b7988ac404b4c0000000000" "1976a914ca6eb218592f289999f13916ee32829ad587dbc588ac00000000") tx_to_validate = Tx.from_hex( "010000000165148d894d3922ef5ffda962be26016635c933d470c8b0ab7618e869e3f70e3c00" "0000008b48304502207f5779ebf4834feaeff4d250898324eb5c0833b16d7af4c1cb0f66f50f" "cf6e85022100b78a65377fd018281e77285efc31e5b9ba7cb7e20e015cf6b7fa3e4a466dd195" "014104072ad79e0aa38c05fa33dd185f84c17f611e58a8658ce996d8b04395b99c7be36529ca" "b7606900a0cd5a7aebc6b233ea8e0fe60943054c63620e05e5b85f0426ffffffff02404b4c00" "000000001976a914d4caa8447532ca8ee4c80a1ae1d230a01e22bfdb88ac8013a0de01000000" "1976a9149661a79ae1f6d487af3420c13e649d6df3747fc288ac00000000") tx_db = {tx.hash(): tx for tx in [input_tx]} tx_to_validate.unspents_from_db(tx_db) self.assertEqual("OP_DUP OP_HASH160 [d4caa8447532ca8ee4c80a1ae1d230a01e22bfdb] OP_EQUALVERIFY OP_CHECKSIG", network.script.disassemble(tx_to_validate.txs_out[0].script)) self.assertEqual(tx_to_validate.id(), "7c4f5385050c18aa8df2ba50da566bbab68635999cc99b75124863da1594195b") annotate_scripts(tx_to_validate, 0) def test_disassemble(self): input_tx = Tx.from_hex( "01000000010000000000000000000000000000000000000000000000000000000000000000" "ffffffff0704ffff001d0134ffffffff0100f2052a0100000043410411db93e1dcdb8a016b" "49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e16" "0bfa9b8b64f9d4c03f999b8643f656b412a3ac00000000") tx_db = {tx.hash(): tx for tx in [input_tx]} tx_to_validate = Tx.from_hex( "0100000001c997a5e56e104102fa209c6a852dd90660a20b2d9c352423edce25857fcd3704000000004847304402" "204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4" "acdd12909d831cc56cbbac4622082221a8768d1d0901ffffffff0200ca9a3b00000000434104ae1a62fe09c5f51b" "13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1ba" "ded5c72a704f7e6cd84cac00286bee0000000043410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482e" "cad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac00000000") tx_to_validate.unspents_from_db(tx_db) self.assertEqual(tx_to_validate.id(), "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16") r = annotate_scripts(tx_to_validate, 0) EXPECTED = [ ( ['--- SIGNATURE SCRIPT START'], 0, 0x47, ('[PUSH_71] 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220' '181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901'), [ 'r: 0x4e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41', 's: 0x181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d09', 'z: 0x7a05c6145f10101e9d6325494245adf1297d80f8f38d4d576d57cdba220bcb19', 'signature type SIGHASH_ALL', (' sig for 1M6HTkQf7RhsrDLDX7Q6GJkxXbTz8VWxMx 1E5CDVQrLjSqTeqfN5zT2X2DoeYS7od2Mi ' '13KiMqUJ7xD6MhUD2k7mKEoZMHDP9HdWwW 12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S') ] ), ( ['--- PUBLIC KEY SCRIPT START'], 0, 0x41, ('[PUSH_65] 0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0ead' 'dfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3'), ['SEC for uncompressed 12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S'] ), ([], 0x42, 0xac, 'OP_CHECKSIG', [])] self.assertEqual(r, EXPECTED) return DisassembleTest
def test_sighash_single(self): for netcode in ["BTC", "XTN"]: self._test_sighash_single(network_for_netcode(netcode))
def make_tests_for_netcode(netcode): network = network_for_netcode(netcode) address_for_script = network.address.for_script script_for_p2pkh = network.contract.for_p2pkh script_for_p2pk = network.contract.for_p2pk script_for_nulldata = network.contract.for_nulldata Tx = network.tx class AddressForScriptTest(unittest.TestCase): def test_script_type_pay_to_address(self): for se in range(1, 100): key = network.keys.private(secret_exponent=se) for b in [True, False]: addr = key.address(is_compressed=b) sc = script_for_p2pkh(key.hash160(is_compressed=b)) afs_address = address_for_script(sc) self.assertEqual(afs_address, addr) def test_solve_pay_to_address(self): for se in range(1, 10): key = network.keys.private(secret_exponent=se) for b in [True, False]: addr = key.address(is_compressed=b) script = script_for_p2pkh(key.hash160(is_compressed=b)) afs_address = address_for_script(script) self.assertEqual(afs_address, addr) hl = network.tx.solve.build_hash160_lookup([se]) tx = Tx(1, [], [Tx.TxOut(100, script)]) tx.sign(hash160_lookup=hl) afs_address = address_for_script(tx.txs_out[0].puzzle_script()) self.assertEqual(afs_address, addr) def test_script_type_pay_to_public_pair(self): for se in range(1, 100): key = network.keys.private(secret_exponent=se) for b in [True, False]: addr = key.address(is_compressed=b) sc = script_for_p2pk(key.sec(is_compressed=b)) afs_address = address_for_script(sc) self.assertEqual(afs_address, addr) def test_solve_pay_to_public_pair(self): for se in range(1, 10): key = network.keys.private(secret_exponent=se) for b in [True, False]: addr = key.address(is_compressed=b) script = script_for_p2pk(key.sec(is_compressed=b)) afs_address = address_for_script(script) self.assertEqual(afs_address, addr) hl = network.tx.solve.build_hash160_lookup([se]) tx = Tx(1, [], [Tx.TxOut(100, script)]) tx.sign(hash160_lookup=hl) afs_address = address_for_script(tx.txs_out[0].puzzle_script()) self.assertEqual(afs_address, addr) def test_weird_tx(self): # this is from tx 12a8d1d62d12307eac6e62f2f14d7e826604e53c320a154593845aa7c8e59fbf afs_address = address_for_script(b'Q') self.assertNotEqual(afs_address, None) self.assertEqual(afs_address, "???") def test_issue_225(self): script = script_for_nulldata(b"foobar") tx_out = Tx.TxOut(1, script) address = address_for_script(tx_out.puzzle_script()) self.assertEqual(address, "(nulldata 666f6f626172)") return AddressForScriptTest
import unittest from pycoin.networks.registry import network_for_netcode from pycoin.ui.key_from_text import key_from_text NETWORKS = [network_for_netcode(_) for _ in ["BTC", "XTN"]] class KeyParserTest(unittest.TestCase): def test_parse_bip32_prv(self): key = key_from_text("xprv9s21ZrQH143K31AgNK5pyVvW23gHnkBq2wh5aEk6g1s496M8ZMjx" "ncCKZKgb5jZoY5eSJMJ2Vbyvi2hbmQnCuHBujZ2WXGTux1X2k9Krdtq", networks=NETWORKS) self.assertEqual( key.secret_exponent(), 0x91880b0e3017ba586b735fe7d04f1790f3c46b818a2151fb2def5f14dd2fd9c3) self.assertEqual(key.address(), "19Vqc8uLTfUonmxUEZac7fz1M5c5ZZbAii") self.assertEqual(key.address(use_uncompressed=True), "1MwkRkogzBRMehBntgcq2aJhXCXStJTXHT") subkey = key.subkey_for_path("0") self.assertEqual(subkey.address(), "1NV3j6NgeAkWBytXiQkWxMFLBtTdbef1rp") def test_parse_bip32_prv_xtn(self): key = key_from_text("tprv8ZgxMBicQKsPdpQD2swL99YVLB6W2GDqNVcCSfAZ9zMXvh6DYj5iJMZmUVrF66" "x7uXBDJSunexZjAtFLtd89iLTWGCEpBdBxs7GTBnEksxV", networks=NETWORKS) self.assertEqual( key.secret_exponent(), 0x91880b0e3017ba586b735fe7d04f1790f3c46b818a2151fb2def5f14dd2fd9c3) self.assertEqual(key.address(), "mp1nuBzKGgv4ZtS5x8YywbCLD5CnVfT7hV") self.assertEqual(key.address(use_uncompressed=True), "n2ThiotfoCrcRofQcFbCrVX2PC89s2KUjh") subkey = key.subkey_for_path("0") self.assertEqual(subkey.address(), "n31129TfTCBky6N9RyitnGTf3t4LYwCV6A")
def create_parser(): codes = network_codes() EPILOG = ('Files are binary by default unless they end with the suffix ".hex". ' + 'Known networks codes:\n ' + ', '.join(['%s (%s)' % (i, network_for_netcode(i).full_name()) for i in codes])) parser = argparse.ArgumentParser( description="Manipulate bitcoin (or alt coin) transactions.", epilog=EPILOG) parser.add_argument('-t', "--transaction-version", type=range_int(0, 255, "version"), help='Transaction version, either 1 (default) or 3 (not yet supported).') parser.add_argument('-l', "--lock-time", type=parse_locktime, help='Lock time; either a block' 'index, or a date/time (example: "2014-01-01T15:00:00"') parser.add_argument('-n', "--network", default=get_current_netcode(), choices=codes, help=('Default network code (environment variable PYCOIN_DEFAULT_NETCODE ' 'or "BTC"=Bitcoin mainnet if unset')) parser.add_argument('-a', "--augment", action='store_true', help='augment tx by adding any missing spendable metadata by fetching' ' inputs from cache and/or web services') parser.add_argument('-s', "--verbose-signature", action='store_true', help='Display technical signature details.') parser.add_argument("-i", "--fetch-spendables", metavar="address", action="append", help='Add all unspent spendables for the given bitcoin address. This information' ' is fetched from web services. With no outputs, incoming spendables will be printed.') parser.add_argument("-I", "--dump-inputs", action='store_true', help='Dump inputs to this transaction.') parser.add_argument( "-k", "--keychain", default=":memory:", help="path to keychain file for hierarchical key hints (SQLite3 file created with keychain tool)") parser.add_argument( "-K", "--key-paths", default="", help="Key path hints to search hiearachical private keys (example: 0/0H/0-20)") parser.add_argument('-f', "--private-key-file", metavar="path-to-private-keys", action="append", default=[], help='file containing WIF or BIP0032 private keys. If file name ends with .gpg, ' '"gpg -d" will be invoked automatically. File is read one line at a time, and if ' 'the file contains only one WIF per line, it will also be scanned for a bitcoin ' 'address, and any addresses found will be assumed to be public keys for the given' ' private key.', type=argparse.FileType('r')) parser.add_argument('-g', "--gpg-argument", help='argument to pass to gpg (besides -d).', default='') parser.add_argument("--remove-tx-in", metavar="tx_in_index_to_delete", action="append", type=int, help='remove a tx_in') parser.add_argument("--remove-tx-out", metavar="tx_out_index_to_delete", action="append", type=int, help='remove a tx_out') parser.add_argument("--replace-input-script", metavar="tx_in_script_slash_hex", action="append", default=[], type=parse_script_index_hex, help='replace an input script: arg looks like "1/796a"') parser.add_argument('-F', "--fee", help='fee, in satoshis, to pay on transaction, or ' '"standard" to auto-calculate. This is only useful if the "split pool" ' 'is used; otherwise, the fee is automatically set to the unclaimed funds.', default="standard", metavar="transaction-fee", type=parse_fee) parser.add_argument('-C', "--cache", help='force the resultant transaction into the transaction cache.' ' Mostly for testing.', action='store_true'), parser.add_argument("--db", help='force the transaction expressed by the given hex ' 'into a RAM-based transaction cache. Mostly for testing.', action="append"), parser.add_argument('-u', "--show-unspents", action='store_true', help='show TxOut items for this transaction in Spendable form.') parser.add_argument('-b', "--bitcoind-url", help='URL to bitcoind instance to validate against (http://user:pass@host:port).') parser.add_argument('-o', "--output-file", metavar="path-to-output-file", type=argparse.FileType('wb'), help='file to write transaction to. This supresses most other output.') parser.add_argument('-d', "--disassemble", action='store_true', help='Disassemble scripts.') parser.add_argument("--pdb", action="store_true", help='Enter PDB debugger on each script instruction.') parser.add_argument("--trace", action='store_true', help='Trace scripts.') parser.add_argument('-p', "--pay-to-script", metavar="pay-to-script", action="append", help='a hex version of a script required for a pay-to-script' 'input (a bitcoin address that starts with 3)') parser.add_argument("--signature", metavar="known-good-signature", action="append", help='a hex version of a signature that will be used if useful') parser.add_argument("--sec", metavar="known-sec", action="append", help='a hex version of an SEC that will be used if useful') parser.add_argument('-P', "--pay-to-script-file", metavar="pay-to-script-file", nargs=1, type=argparse.FileType('r'), help='a file containing hex scripts ' '(one per line) corresponding to pay-to-script inputs') parser.add_argument("--dump-signatures", action="store_true", help="print signatures (for use with --signature)") parser.add_argument("--dump-secs", action="store_true", help="print secs (for use with --sec)") parser.add_argument("--coinbase", type=str, help="add an input as a coinbase from the given address") parser.add_argument("argument", nargs="*", help='generic argument: can be a hex transaction id ' '(exactly 64 characters) to be fetched from cache or a web service;' ' a transaction as a hex string; a path name to a transaction to be loaded;' ' a spendable 4-tuple of the form tx_id/tx_out_idx/script_hex/satoshi_count ' 'to be added to TxIn list; an address/satoshi_count to be added to the TxOut ' 'list; an address or script to be added to the TxOut list and placed in the ' '"split pool".') return parser
def parse_context(args, parser): network = network_for_netcode(args.network) tx_class = network.tx # defaults spendables = [] payables = [] # we create the tx_db lazily tx_db = None if args.db: try: txs = [tx_class.from_hex(tx_hex) for tx_hex in args.db or []] except Exception: parser.error("can't parse ") the_ram_tx_db = dict((tx.hash(), tx) for tx in txs) if tx_db is None: tx_db = create_tx_db(network) tx_db.lookup_methods.append(the_ram_tx_db.get) txs = [] if args.coinbase: coinbase_tx = build_coinbase_tx(network, args.coinbase) txs.append(coinbase_tx) keychain = network.keychain(sqlite3.connect(args.keychain)) # there are a few warnings we might optionally print out, but only if # they are relevant. We don't want to print them out multiple times, so we # collect them here and print them at the end if they ever kick in. warning_spendables = None for arg in args.argument: tx, tx_db = parse_tx(tx_class, arg, parser, tx_db, network) if tx: txs.append(tx) continue if key_found(arg, keychain, args.key_paths, network): continue if parse_parts(tx_class, arg, spendables, payables, network): continue payable = script_for_address_or_opcodes(network, arg) if payable is not None: payables.append((payable, 0)) continue parser.error("can't parse %s" % arg) parse_private_key_file(args, keychain, network) if args.fetch_spendables: warning_spendables = message_about_spendables_for_address_env(args.network) for address in args.fetch_spendables: spendables.extend(spendables_for_address(address, args.network)) return (network, txs, spendables, payables, keychain, tx_db, warning_spendables)