Exemplo n.º 1
0
 def __init__(self, wordfile = 'wordlist.txt'):
     
     # Read create the mnemonic wordlist object
     self.mnemonic = Mnemonic("english")
 
     # Set up a default reference wallet
     self.wallet = Wallet.from_master_secret(bytes(0))
     
     # Set up a Polly communication pipe
     self.polly = PollyCom()
     
     # Default print padding
     self.PAD = "{:35}"
Exemplo n.º 2
0
    def __init__(self, wordfile='wordlist.txt'):

        # Read create the mnemonic wordlist object
        self.mnemonic = Mnemonic("english")

        # Set up a default reference wallet
        self.wallet = Wallet.from_master_secret(bytes(0))

        # Set up a Polly communication pipe
        self.polly = PollyCom()

        # Default print padding
        self.PAD = "{:35}"
Exemplo n.º 3
0
    def test_is_public_private_bip32_valid(self):
        WALLET_KEYS = ["foo", "1", "2", "3", "4", "5"]

        # not all networks support BIP32 yet
        for netcode in "BTC XTN DOGE".split():
            for wk in WALLET_KEYS:
                wallet = Wallet.from_master_secret(wk.encode("utf8"), netcode=netcode)
                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)
Exemplo n.º 4
0
    def test_is_public_private_bip32_valid(self):
        WALLET_KEYS = ["foo", "1", "2", "3", "4", "5"]

        # not all networks support BIP32 yet
        for netcode in "BTC XTN DOGE".split():
            for wk in WALLET_KEYS:
                wallet = Wallet.from_master_secret(wk.encode("utf8"),
                                                   netcode=netcode)
                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)
Exemplo n.º 5
0
 def test_set_seed(self, wordlist):
     """
     Sets the wallet seed for Polly and the reference wallet.
     
     Note: Subsequent tests will use the seed set by this routine.
     
     wordlist -  a space separated string of 18 mnemonic words from the Polly wordlist.
                 Note: the checksum must be correct (part of the 18th word) - see BIP0039.
                 gen_wordlist can be used to generate a wordlist including the proper checksum.
     """
     
     assert len(wordlist.split(" ")) == 18, "expecting 18 words"
     assert self.mnemonic.check(wordlist) == True, "invalid word list"
     
     print (self.PAD.format("Set seed"), end='')
     
     # Set polly
     self.polly.send_set_master_seed(wordlist)
     print (self.__outok())
     
     # Set the reference wallet
     seed = self.mnemonic.to_seed(wordlist)
     self.wallet = Wallet.from_master_secret(seed)
Exemplo n.º 6
0
    def test_set_seed(self, wordlist):
        """
        Sets the wallet seed for Polly and the reference wallet.
        
        Note: Subsequent tests will use the seed set by this routine.
        
        wordlist -  a space separated string of 18 mnemonic words from the Polly wordlist.
                    Note: the checksum must be correct (part of the 18th word) - see BIP0039.
                    gen_wordlist can be used to generate a wordlist including the proper checksum.
        """

        assert len(wordlist.split(" ")) == 18, "expecting 18 words"
        assert self.mnemonic.check(wordlist) == True, "invalid word list"

        print(self.PAD.format("Set seed"), end='')

        # Set polly
        self.polly.send_set_master_seed(wordlist)
        print(self.__outok())

        # Set the reference wallet
        seed = self.mnemonic.to_seed(wordlist)
        self.wallet = Wallet.from_master_secret(seed)
Exemplo n.º 7
0
def main():
    parser = argparse.ArgumentParser(description="Generate a private wallet key. WARNING: obsolete. Use ku instead.")

    parser.add_argument('-a', "--address", help='show as Bitcoin address', action='store_true')
    parser.add_argument('-i', "--info", help='show metadata', action='store_true')
    parser.add_argument('-j', "--json", help='output metadata as JSON', action='store_true')
    parser.add_argument('-w', "--wif", help='show as Bitcoin WIF', action='store_true')
    parser.add_argument('-f', "--wallet-key-file", help='initial wallet key', type=argparse.FileType('r'))
    parser.add_argument('-k', "--wallet-key", help='initial wallet key')
    parser.add_argument('-g', "--gpg", help='use gpg --gen-random to get additional entropy', action='store_true')
    parser.add_argument('-u', "--dev-random", help='use /dev/random to get additional entropy', action='store_true')
    parser.add_argument('-n', "--uncompressed", help='show in uncompressed form', action='store_true')
    parser.add_argument('-p', help='generate wallet key from passphrase. NOT RECOMMENDED', metavar='passphrase')
    parser.add_argument('-s', "--subkey", help='subkey path (example: 0p/2/1)')
    parser.add_argument('-t', help='generate test key', action="store_true")
    parser.add_argument('inputfile', help='source of entropy. stdin by default', type=argparse.FileType(mode='r+b'), nargs='?')
    args = parser.parse_args()

    # args.inputfile doesn't like binary when "-" is passed in. Deal with this.
    if args.inputfile == sys.stdin:
        args.inputfile = sys.stdin.buffer

    network = 'T' if args.t else 'M'

    entropy = bytearray()
    if args.gpg:
        entropy.extend(gpg_entropy())
    if args.dev_random:
        entropy.extend(dev_random_entropy())
    if args.inputfile:
        entropy.extend(args.inputfile.read())
    if args.p:
        entropy.extend(args.p.encode("utf8"))
    if len(entropy) == 0 and not args.wallet_key and not args.wallet_key_file:
        parser.error("you must specify at least one source of entropy")
    if args.wallet_key and len(entropy) > 0:
        parser.error("don't specify both entropy and a wallet key")
    if args.wallet_key_file:
        wallet = Wallet.from_wallet_key(args.wallet_key_file.readline()[:-1])
    elif args.wallet_key:
        wallet = Wallet.from_wallet_key(args.wallet_key)
    else:
        wallet = Wallet.from_master_secret(bytes(entropy), netcode=network)
    try:
        if args.subkey:
            wallet = wallet.subkey_for_path(args.subkey)
        if wallet.child_number >= 0x80000000:
            wc = wallet.child_number - 0x80000000
            child_index = "%dp (%d)" % (wc, wallet.child_number)
        else:
            child_index = "%d" % wallet.child_number
        if args.json:
            d = dict(
                wallet_key=wallet.wallet_key(as_private=wallet.is_private),
                public_pair_x=wallet.public_pair[0],
                public_pair_y=wallet.public_pair[1],
                tree_depth=wallet.depth,
                fingerprint=b2h(wallet.fingerprint()),
                parent_fingerprint=b2h(wallet.parent_fingerprint),
                child_index=child_index,
                chain_code=b2h(wallet.chain_code),
                bitcoin_addr=wallet.bitcoin_address(),
                bitcoin_addr_uncompressed=wallet.bitcoin_address(compressed=False),
                network="test" if wallet.is_test else "main",
            )
            if wallet.is_private:
                d.update(dict(
                    key="private",
                    secret_exponent=wallet.secret_exponent,
                    WIF=wallet.wif(),
                    WIF_uncompressed=wallet.wif(compressed=False)
                ))
            else:
                d.update(dict(key="public"))
            print(json.dumps(d, indent=3))
        elif args.info:
            print(wallet.wallet_key(as_private=wallet.is_private))
            if wallet.is_test:
                print("test network")
            else:
                print("main network")
            if wallet.is_private:
                print("private key")
                print("secret exponent: %d" % wallet.secret_exponent)
            else:
                print("public key only")
            print("public pair x:   %d\npublic pair y:   %d" % wallet.public_pair)
            print("tree depth:      %d" % wallet.depth)
            print("fingerprint:     %s" % b2h(wallet.fingerprint()))
            print("parent f'print:  %s" % b2h(wallet.parent_fingerprint))
            print("child index:     %s" % child_index)
            print("chain code:      %s" % b2h(wallet.chain_code))
            if wallet.is_private:
                print("WIF:             %s" % wallet.wif())
                print("  uncompressed:  %s" % wallet.wif(compressed=False))
            print("Bitcoin address: %s" % wallet.bitcoin_address())
            print("  uncompressed:  %s" % wallet.bitcoin_address(compressed=False))
        elif args.address:
            print(wallet.bitcoin_address(compressed=not args.uncompressed))
        elif args.wif:
            print(wallet.wif(compressed=not args.uncompressed))
        else:
            print(wallet.wallet_key(as_private=wallet.is_private))
    except PublicPrivateMismatchError as ex:
        print(ex.args[0])
Exemplo n.º 8
0
def main():
    networks = "MTLD"
    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, full_network_name_for_netcode(i)) for i in NETWORK_NAMES])
    )
    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('-s',
                        "--subkey",
                        help='subkey path (example: 0H/2/15-20)')
    parser.add_argument('-n',
                        "--network",
                        help='specify network (default: BTC = Bitcoin)',
                        default='BTC',
                        choices=NETWORK_NAMES)
    parser.add_argument("--override-network",
                        help='override detected network type',
                        default=None,
                        choices=NETWORK_NAMES)

    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);'
        ' 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)')

    args = parser.parse_args()

    if args.override_network:
        # force network arg to match override, but also will override decoded data below.
        args.network = args.override_network

    PREFIX_TRANSFORMS = (
        ("P:", lambda s: Key(hierarchical_wallet=Wallet.from_master_secret(
            s.encode("utf8"), netcode=args.network))),
        ("H:", lambda s: Key(hierarchical_wallet=Wallet.from_master_secret(
            h2b(s), netcode=args.network))),
        ("create", lambda s: Key(hierarchical_wallet=Wallet.from_master_secret(
            get_entropy(), netcode=args.network))),
    )

    for item in args.item:
        key = None
        for k, f in PREFIX_TRANSFORMS:
            if item.startswith(k):
                try:
                    key = f(item[len(k):])
                    break
                except Exception:
                    pass
        else:
            try:
                key = Key.from_text(item)
            except encoding.EncodingError:
                pass
        if key is None:
            secret_exponent = parse_as_secret_exponent(item)
            if secret_exponent:
                key = Key(secret_exponent=secret_exponent,
                          netcode=args.network)

        if SEC_RE.match(item):
            key = Key.from_sec(h2b(item))

        if key is None:
            public_pair = parse_as_public_pair(item)
            if public_pair:
                key = Key(public_pair=public_pair, netcode=args.network)

        if HASH160_RE.match(item):
            key = Key(hash160=h2b(item), netcode=args.network)

        if key is None:
            print("can't parse %s" % item, file=sys.stderr)
            continue

        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.
            # XXX public interface for this is needed...
            key._netcode = args.override_network
            key._hierarchical_wallet.netcode = args.override_network

        for key in key.subkeys(args.subkey or ""):
            if args.public:
                key = key.public_copy()

            output_dict, output_order = create_output(item, key)

            if args.json:
                print(json.dumps(output_dict, indent=3, sort_keys=True))
            elif args.wallet:
                print(output_dict["wallet_key"])
            elif args.wif:
                print(output_dict["wif_uncompressed" if args.
                                  uncompressed else "wif"])
            elif args.address:
                print(output_dict[args.network.lower() + "_address" +
                                  ("_uncompressed"
                                   if args.uncompressed else "")])
            else:
                dump_output(output_dict, output_order)
Exemplo n.º 9
0
def main():
    networks = "MTLD"
    parser = argparse.ArgumentParser(
        description='Crypto coin utility ku ("key utility") to show'
        ' information about Bitcoin or other cryptocoin data structures.')
    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('-s', "--subkey", help='subkey path (example: 0H/2/15-20)')
    parser.add_argument('-n', "--network", help='specify network (one of %s)' % networks, default='M')

    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);'
        ' 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)')

    args = parser.parse_args()

    PREFIX_TRANSFORMS = (
        ("P:", lambda s:
            Key(hierarchical_wallet=Wallet.from_master_secret(s.encode("utf8"), netcode=args.network))),
        ("H:", lambda s:
            Key(hierarchical_wallet=Wallet.from_master_secret(h2b(s), netcode=args.network))),
        ("create", lambda s:
            Key(hierarchical_wallet=Wallet.from_master_secret(get_entropy(), netcode=args.network))),
    )

    for item in args.item:
        key = None
        for k, f in PREFIX_TRANSFORMS:
            if item.startswith(k):
                try:
                    key = f(item[len(k):])
                    break
                except Exception:
                    pass
        else:
            try:
                key = Key.from_text(item)
            except encoding.EncodingError:
                pass
        if key is None:
            secret_exponent = parse_as_secret_exponent(item)
            if secret_exponent:
                key = Key(secret_exponent=secret_exponent, netcode=args.network)

        if SEC_RE.match(item):
            key = Key.from_sec(h2b(item))

        if key is None:
            public_pair = parse_as_public_pair(item)
            if public_pair:
                key = Key(public_pair=public_pair, netcode=args.network)

        if HASH160_RE.match(item):
            key = Key(hash160=h2b(item), netcode=args.network)

        if key is None:
            print("can't parse %s" % item, file=sys.stderr)
            continue

        for key in key.subkeys(args.subkey or ""):
            if args.public:
                key = key.public_copy()

            output_dict, output_order = create_output(item, key)

            if args.json:
                print(json.dumps(output_dict, indent=3))
            elif args.wallet:
                print(output_dict["wallet_key"])
            elif args.wif:
                print(output_dict["wif_uncompressed" if args.uncompressed else "wif"])
            elif args.address:
                print(output_dict[
                    "bitcoin_address_uncompressed" if args.uncompressed else "bitcoin_address"])
            else:
                dump_output(output_dict, output_order)
Exemplo n.º 10
0
def main():
    networks = "MTLD"
    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, full_network_name_for_netcode(i)) for i in NETWORK_NAMES])
    )
    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('-s', "--subkey", help='subkey path (example: 0H/2/15-20)')
    parser.add_argument('-n', "--network", help='specify network (default: BTC = Bitcoin)',
                                default='BTC', choices=NETWORK_NAMES)
    parser.add_argument("--override-network", help='override detected network type',
                                default=None, choices=NETWORK_NAMES)

    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);'
        ' 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)')

    args = parser.parse_args()

    if args.override_network:
        # force network arg to match override, but also will override decoded data below.
        args.network = args.override_network

    PREFIX_TRANSFORMS = (
        ("P:", lambda s:
            Key(hierarchical_wallet=Wallet.from_master_secret(s.encode("utf8"), netcode=args.network))),
        ("H:", lambda s:
            Key(hierarchical_wallet=Wallet.from_master_secret(h2b(s), netcode=args.network))),
        ("create", lambda s:
            Key(hierarchical_wallet=Wallet.from_master_secret(get_entropy(), netcode=args.network))),
    )

    for item in args.item:
        key = None
        for k, f in PREFIX_TRANSFORMS:
            if item.startswith(k):
                try:
                    key = f(item[len(k):])
                    break
                except Exception:
                    pass
        else:
            try:
                key = Key.from_text(item)
            except encoding.EncodingError:
                pass
        if key is None:
            secret_exponent = parse_as_secret_exponent(item)
            if secret_exponent:
                key = Key(secret_exponent=secret_exponent, netcode=args.network)

        if SEC_RE.match(item):
            key = Key.from_sec(h2b(item))

        if key is None:
            public_pair = parse_as_public_pair(item)
            if public_pair:
                key = Key(public_pair=public_pair, netcode=args.network)

        if HASH160_RE.match(item):
            key = Key(hash160=h2b(item), netcode=args.network)

        if key is None:
            print("can't parse %s" % item, file=sys.stderr)
            continue

        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.
            # XXX public interface for this is needed...
            key._netcode = args.override_network
            key._hierarchical_wallet.netcode = args.override_network

        for key in key.subkeys(args.subkey or ""):
            if args.public:
                key = key.public_copy()

            output_dict, output_order = create_output(item, key)

            if args.json:
                print(json.dumps(output_dict, indent=3, sort_keys=True))
            elif args.wallet:
                print(output_dict["wallet_key"])
            elif args.wif:
                print(output_dict["wif_uncompressed" if args.uncompressed else "wif"])
            elif args.address:
                print(output_dict[ args.network.lower() + "_address" +
                    ("_uncompressed" if args.uncompressed else "")])
            else:
                dump_output(output_dict, output_order)
Exemplo n.º 11
0
#!/usr/bin/python
import os

from pycoin.key.bip32 import Wallet
from pycoin.encoding import public_pair_to_hash160_sec, hash160_sec_to_bitcoin_address
from pycoin.networks import address_prefix_for_netcode, alternate_hash_for_netcode
from binascii import hexlify
import bitcoinrpc
import socket

secret = os.urandom(64)
wallet = Wallet.from_master_secret(bytes(secret), 'BLC')

sec = public_pair_to_hash160_sec(wallet.public_pair)
pubkey = ''.join('{:02x}'.format(ord(x)) for x in sec)

addr_blc = hash160_sec_to_bitcoin_address(sec, address_prefix=address_prefix_for_netcode('BLC'), internal_hash=alternate_hash_for_netcode('BLC'))
addr_pho = hash160_sec_to_bitcoin_address(sec, address_prefix=address_prefix_for_netcode('PHO'), internal_hash=alternate_hash_for_netcode('PHO'))
addr_bbtc = hash160_sec_to_bitcoin_address(sec, address_prefix=address_prefix_for_netcode('BBTC'), internal_hash=alternate_hash_for_netcode('BBTC'))
addr_xdq = hash160_sec_to_bitcoin_address(sec, address_prefix=address_prefix_for_netcode('XDQ'), internal_hash=alternate_hash_for_netcode('XDQ'))
addr_elt = hash160_sec_to_bitcoin_address(sec, address_prefix=address_prefix_for_netcode('ELT'), internal_hash=alternate_hash_for_netcode('ELT'))
addr_umo = hash160_sec_to_bitcoin_address(sec, address_prefix=address_prefix_for_netcode('UMO'), internal_hash=alternate_hash_for_netcode('UMO'))

addresses = {
    'blakecoin': addr_blc,
    'photon': addr_pho,
    'blakebitcoin': addr_bbtc,
    'dirac': addr_xdq,
    'electron': addr_elt,
    'universalmolecule': addr_umo
}
Exemplo n.º 12
0
    def test_sign(self, keynums_satoshi, out_addr, out_satoshi, change_keynum, change_satoshi, prevtx_keynums, prevtx_outputs, prevtx_inputs):
        """
        Performs a tx signing test, comparing Polly's signed tx against the reference wallet.
    
        Basic tx signing parameters:
        
        keynums_satoshi - list of tuples (keynum, satoshis) with key indices and their unspent value to 
                          use as tx inputs. Funding above out_satoshi + change_satoshi will be fees.
        out_addr        - output address in bitcoin address format. 
        out_satoshi     - output amount in satoshis.
        change_keynum   - change key index in the wallet, use None for no change.
        change_satoshi  - change amount in satoshis, use 0 for no change. 
        
        
        Supporting (previous) txs will be created to fund keynums and are controlled by these parameters:
        
        prevtx_keynums  - keynums will show up as outputs of previous txs. A number randomly picked 
                          from this list controls how many keynums are chosen to include per prev tx.
        prevtx_outputs  - in addition to previous tx outputs funding keynums, other outputs may 
                          be present. A number randomly picked from this list controls how many 
                          ignored outputs are injected per keynum. 
        prevtx_inputs   - previous txs need inputs too. A number randomly picked from this list 
                          controls how many inputs are chosen per previous tx.
        """
        
        total_in_satoshi = sum(satoshi for _, satoshi in keynums_satoshi) 
        fee_satoshi      = total_in_satoshi - out_satoshi - change_satoshi
        chain0           = self.wallet.subkey(0, is_hardened = True).subkey(0)
        chain1           = self.wallet.subkey(0, is_hardened = True).subkey(1)
        
        assert total_in_satoshi >= out_satoshi + change_satoshi
        assert len(keynums_satoshi) <= 32
    
        #
        # Step 1: send the inputs and outputs to use in the signed tx
        #
        
        # Create the (key num, compressed public key) tuple, input keys assume an m/0h/0/keynum path for now. 
        keys = [(keynum, encoding.public_pair_to_sec(chain0.subkey(keynum).public_pair)) 
                for (keynum, _) in keynums_satoshi] 
        
        # Convert base58 address to raw hex address
        out_addr_160 = encoding.bitcoin_address_to_hash160_sec(out_addr)
        
        print()
        print("Sign tx parameters:", "")
        for i, (keynum, satoshi) in enumerate(keynums_satoshi):
            print("{:<10}{:16.8f} btc < key {}".format (" inputs" if 0 == i else "", satoshi          / 100000000, keynum))
        print("{:<10}{:16.8f} btc > {}".format         (" output",                   out_satoshi      / 100000000, self.hexstr(out_addr_160)))
        print("{:<10}{:16.8f} btc > key {}".format     (" change",                   change_satoshi   / 100000000, change_keynum))
        print("{:<10}{:16.8f} btc".format              (" fee",                      fee_satoshi      / 100000000))
        print("{:<10}{:16.8f} btc".format              (" total",                    total_in_satoshi / 100000000))
       
        print()
        print(self.PAD.format("Send tx parameters"), end='')
        
        # ---> send to Polly 
        self.polly.send_sign_tx(keys, out_addr_160, out_satoshi, change_keynum, change_satoshi) 

        print(self.__outok())
    
        #
        # Step 2: send previous txs to fund the inputs
        #
    
        print()

        cur = 0
        prevtx_info = []
    
        while cur < len(keynums_satoshi) :
    
            prevtx_outputs_satoshi = []
            
            # Calculate how many keynums will be associated with this prev tx
            end = min(cur + random.choice(prevtx_keynums), len(keynums_satoshi))
            
            # Create the prev tx output list
            for keynum, satoshi in keynums_satoshi[cur:end] :
        
                # Inject a random number of outputs not associated with tx input keynums
                for _ in range(0, random.choice(prevtx_outputs)) :
                    prevtx_outputs_satoshi.append((random.randint(0, 0x7FFFFFFF),  
                                                    random.randint(0, 2099999997690000)))
    
                # Add the outputs funding the tx input keynums 
                prevtx_outputs_satoshi.append((keynum, satoshi))
    
                # Create output script
                addr   = chain0.subkey(keynum, as_private = True).bitcoin_address()
                script = standard_tx_out_script(addr)
    
                # Capture some info we'll use later to verify the signed tx
                prevtx_info.append((keynum, 
                                    satoshi,
                                    script,
                                    0,                                # This is the hash and will be replaced later
                                    len(prevtx_outputs_satoshi) - 1)) # Index of the valid output
                
            print("{:30}{}".format("Make prev tx for keys", " ".join(str(keynum) for (keynum, _, _, _, _) in prevtx_info[cur:])))
            
            # Create the prev tx
            prevtx = self.create_prev_tx(win                 = Wallet.from_master_secret(bytes(0)), # create a dummy wallet 
                                         in_keynum           = list(range(0, random.choice(prevtx_inputs))), 
                                         sources_per_input   = 1, 
                                         wout                = chain0, 
                                         out_keynum_satoshi  = prevtx_outputs_satoshi, 
                                         fees_satoshi        = random.randint(100, 1000))
            
            # We have built the prev tx, calculate its hash (and reverse the bytes) 
            prevtx_hash = encoding.double_sha256(prevtx)[::-1] 
    
            # Update the hashes now that we have a full prev tx
            for i, (keynum, satoshi, script, _, outidx) in enumerate(prevtx_info[cur:]) :
                prevtx_info[i + cur] = (keynum, satoshi, script, prevtx_hash, outidx)
                
            # Create the index table that matches a keynum index with an ouput index in this prev tx
            idx_table = [(keynum_idx + cur, outidx) for keynum_idx, (_, _, _, _, outidx) in enumerate(prevtx_info[cur:])] 
            
            print(self.PAD.format("Send prev tx "), end='')
            
            # ---> send to Polly
            self.polly.send_prev_tx(idx_table, prevtx)
    
            print(self.__outok())
    
            cur = end
        
        #
        # Step 3: generate a signed tx with the reference wallet and compare against Polly's
        #
    
        spendables = []
        wifs       = []
        
        # Make sure that the inputs add up correctly, and prep the input_sources for reference wallet signing
        for (keynum, satoshi, script, prevtx_hash, outidx) in prevtx_info:
            spendables.append(Spendable(satoshi, script, prevtx_hash, outidx))
            wifs.append(chain0.subkey(keynum, as_private = True).wif())
        
        change_addr = chain1.subkey(change_keynum).bitcoin_address()
        
        payables = [(out_addr, out_satoshi), (change_addr, change_satoshi)]
        
        print()
        print(self.PAD.format("Make reference signature"))
    
        signed_tx     = create_signed_tx(spendables, payables, wifs, fee_satoshi)
        signed_tx     = self.get_tx_bytes(signed_tx)
        
        print(self.PAD.format("Get signed tx"), end='', flush = True)
        
        # <--- get the signed tx from Polly
        polly_signed_tx = self.polly.send_get_signed_tx()

        #print(self.txstr(polly_signed_tx))
        #print(self.txstr(signed_tx))
        
        print(self.__outok())
        
        # Compare reference wallet signed tx with polly's 
        assert signed_tx == polly_signed_tx, "test_sign: signature mismatch\nExpected:\n" + self.hexstr(signed_tx) + "\n\nActual:\n" + self.hexstr(polly_signed_tx)
Exemplo n.º 13
0
    def test_ref_bip32(self):
        """
        Performs a test of the reference wallet's BIP32 key generation capability.
        """

        # BIP32 test vectors, see https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#Test_Vectors

        # Vector 1

        m = Wallet.from_master_secret(
            bytes.fromhex("000102030405060708090a0b0c0d0e0f"))

        assert m.wallet_key(
        ) == "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
        assert m.wallet_key(
            as_private=True
        ) == "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"
        assert m.bitcoin_address() == "15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma"
        assert m.wif(
        ) == "L52XzL2cMkHxqxBXRyEpnPQZGUs3uKiL3R11XbAdHigRzDozKZeW"

        m0h = m.subkey(is_hardened=True)
        assert m0h.wallet_key(
        ) == "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"
        assert m0h.wallet_key(
            as_private=True
        ) == "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7"

        m0h1 = m0h.subkey(i=1)
        assert m0h1.wallet_key(
        ) == "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"
        assert m0h1.wallet_key(
            as_private=True
        ) == "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs"

        m0h1_1_2h = m0h1.subkey(i=2, is_hardened=True)
        assert m0h1_1_2h.wallet_key(
        ) == "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5"
        assert m0h1_1_2h.wallet_key(
            as_private=True
        ) == "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM"

        m0h1_1_2h_2 = m0h1_1_2h.subkey(i=2)
        assert m0h1_1_2h_2.wallet_key(
        ) == "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"
        assert m0h1_1_2h_2.wallet_key(
            as_private=True
        ) == "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334"

        m0h1_1_2h_2_1000000000 = m0h1_1_2h_2.subkey(i=1000000000)
        assert m0h1_1_2h_2_1000000000.wallet_key(
        ) == "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"
        assert m0h1_1_2h_2_1000000000.wallet_key(
            as_private=True
        ) == "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76"

        # Vector 2

        m = Wallet.from_master_secret(
            bytes.fromhex(
                "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"
            ))

        assert m.wallet_key(
        ) == "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"
        assert m.wallet_key(
            as_private=True
        ) == "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U"

        m0 = m.subkey()
        assert m0.wallet_key(
        ) == "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"
        assert m0.wallet_key(
            as_private=True
        ) == "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt"

        m0_2147483647p = m0.subkey(i=2147483647, is_hardened=True)
        assert m0_2147483647p.wallet_key(
        ) == "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a"
        assert m0_2147483647p.wallet_key(
            as_private=True
        ) == "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9"

        m0_2147483647p_1 = m0_2147483647p.subkey(i=1)
        assert m0_2147483647p_1.wallet_key(
        ) == "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon"
        assert m0_2147483647p_1.wallet_key(
            as_private=True
        ) == "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef"

        m0_2147483647p_1_2147483646p = m0_2147483647p_1.subkey(
            i=2147483646, is_hardened=True)
        assert m0_2147483647p_1_2147483646p.wallet_key(
        ) == "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"
        assert m0_2147483647p_1_2147483646p.wallet_key(
            as_private=True
        ) == "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc"

        m0_2147483647p_1_2147483646p_2 = m0_2147483647p_1_2147483646p.subkey(
            i=2)
        assert m0_2147483647p_1_2147483646p_2.wallet_key(
        ) == "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"
        assert m0_2147483647p_1_2147483646p_2.wallet_key(
            as_private=True
        ) == "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j"
Exemplo n.º 14
0
    def test_sign(self, keynums_satoshi, out_addr, out_satoshi, change_keynum,
                  change_satoshi, prevtx_keynums, prevtx_outputs,
                  prevtx_inputs):
        """
        Performs a tx signing test, comparing Polly's signed tx against the reference wallet.
    
        Basic tx signing parameters:
        
        keynums_satoshi - list of tuples (keynum, satoshis) with key indices and their unspent value to 
                          use as tx inputs. Funding above out_satoshi + change_satoshi will be fees.
        out_addr        - output address in bitcoin address format. 
        out_satoshi     - output amount in satoshis.
        change_keynum   - change key index in the wallet, use None for no change.
        change_satoshi  - change amount in satoshis, use 0 for no change. 
        
        
        Supporting (previous) txs will be created to fund keynums and are controlled by these parameters:
        
        prevtx_keynums  - keynums will show up as outputs of previous txs. A number randomly picked 
                          from this list controls how many keynums are chosen to include per prev tx.
        prevtx_outputs  - in addition to previous tx outputs funding keynums, other outputs may 
                          be present. A number randomly picked from this list controls how many 
                          ignored outputs are injected per keynum. 
        prevtx_inputs   - previous txs need inputs too. A number randomly picked from this list 
                          controls how many inputs are chosen per previous tx.
        """

        total_in_satoshi = sum(satoshi for _, satoshi in keynums_satoshi)
        fee_satoshi = total_in_satoshi - out_satoshi - change_satoshi
        chain0 = self.wallet.subkey(0, is_hardened=True).subkey(0)
        chain1 = self.wallet.subkey(0, is_hardened=True).subkey(1)

        assert total_in_satoshi >= out_satoshi + change_satoshi
        assert len(keynums_satoshi) <= 32

        #
        # Step 1: send the inputs and outputs to use in the signed tx
        #

        # Create the (key num, compressed public key) tuple, input keys assume an m/0h/0/keynum path for now.
        keys = [
            (keynum,
             encoding.public_pair_to_sec(chain0.subkey(keynum).public_pair))
            for (keynum, _) in keynums_satoshi
        ]

        # Convert base58 address to raw hex address
        out_addr_160 = encoding.bitcoin_address_to_hash160_sec(out_addr)

        print()
        print("Sign tx parameters:", "")
        for i, (keynum, satoshi) in enumerate(keynums_satoshi):
            print("{:<10}{:16.8f} btc < key {}".format(
                " inputs" if 0 == i else "", satoshi / 100000000, keynum))
        print("{:<10}{:16.8f} btc > {}".format(" output",
                                               out_satoshi / 100000000,
                                               self.hexstr(out_addr_160)))
        print("{:<10}{:16.8f} btc > key {}".format(" change",
                                                   change_satoshi / 100000000,
                                                   change_keynum))
        print("{:<10}{:16.8f} btc".format(" fee", fee_satoshi / 100000000))
        print("{:<10}{:16.8f} btc".format(" total",
                                          total_in_satoshi / 100000000))

        print()
        print(self.PAD.format("Send tx parameters"), end='')

        # ---> send to Polly
        self.polly.send_sign_tx(keys, out_addr_160, out_satoshi, change_keynum,
                                change_satoshi)

        print(self.__outok())

        #
        # Step 2: send previous txs to fund the inputs
        #

        print()

        cur = 0
        prevtx_info = []

        while cur < len(keynums_satoshi):

            prevtx_outputs_satoshi = []

            # Calculate how many keynums will be associated with this prev tx
            end = min(cur + random.choice(prevtx_keynums),
                      len(keynums_satoshi))

            # Create the prev tx output list
            for keynum, satoshi in keynums_satoshi[cur:end]:

                # Inject a random number of outputs not associated with tx input keynums
                for _ in range(0, random.choice(prevtx_outputs)):
                    prevtx_outputs_satoshi.append(
                        (random.randint(0, 0x7FFFFFFF),
                         random.randint(0, 2099999997690000)))

                # Add the outputs funding the tx input keynums
                prevtx_outputs_satoshi.append((keynum, satoshi))

                # Create output script
                addr = chain0.subkey(keynum, as_private=True).bitcoin_address()
                script = standard_tx_out_script(addr)

                # Capture some info we'll use later to verify the signed tx
                prevtx_info.append((
                    keynum,
                    satoshi,
                    script,
                    0,  # This is the hash and will be replaced later
                    len(prevtx_outputs_satoshi) -
                    1))  # Index of the valid output

            print("{:30}{}".format(
                "Make prev tx for keys", " ".join(
                    str(keynum)
                    for (keynum, _, _, _, _) in prevtx_info[cur:])))

            # Create the prev tx
            prevtx = self.create_prev_tx(
                win=Wallet.from_master_secret(
                    bytes(0)),  # create a dummy wallet 
                in_keynum=list(range(0, random.choice(prevtx_inputs))),
                sources_per_input=1,
                wout=chain0,
                out_keynum_satoshi=prevtx_outputs_satoshi,
                fees_satoshi=random.randint(100, 1000))

            # We have built the prev tx, calculate its hash (and reverse the bytes)
            prevtx_hash = encoding.double_sha256(prevtx)[::-1]

            # Update the hashes now that we have a full prev tx
            for i, (keynum, satoshi, script, _,
                    outidx) in enumerate(prevtx_info[cur:]):
                prevtx_info[i + cur] = (keynum, satoshi, script, prevtx_hash,
                                        outidx)

            # Create the index table that matches a keynum index with an ouput index in this prev tx
            idx_table = [
                (keynum_idx + cur, outidx)
                for keynum_idx, (_, _, _, _,
                                 outidx) in enumerate(prevtx_info[cur:])
            ]

            print(self.PAD.format("Send prev tx "), end='')

            # ---> send to Polly
            self.polly.send_prev_tx(idx_table, prevtx)

            print(self.__outok())

            cur = end

        #
        # Step 3: generate a signed tx with the reference wallet and compare against Polly's
        #

        spendables = []
        wifs = []

        # Make sure that the inputs add up correctly, and prep the input_sources for reference wallet signing
        for (keynum, satoshi, script, prevtx_hash, outidx) in prevtx_info:
            spendables.append(Spendable(satoshi, script, prevtx_hash, outidx))
            wifs.append(chain0.subkey(keynum, as_private=True).wif())

        change_addr = chain1.subkey(change_keynum).bitcoin_address()

        payables = [(out_addr, out_satoshi), (change_addr, change_satoshi)]

        print()
        print(self.PAD.format("Make reference signature"))

        signed_tx = create_signed_tx(spendables, payables, wifs, fee_satoshi)
        signed_tx = self.get_tx_bytes(signed_tx)

        print(self.PAD.format("Get signed tx"), end='', flush=True)

        # <--- get the signed tx from Polly
        polly_signed_tx = self.polly.send_get_signed_tx()

        #print(self.txstr(polly_signed_tx))
        #print(self.txstr(signed_tx))

        print(self.__outok())

        # Compare reference wallet signed tx with polly's
        assert signed_tx == polly_signed_tx, "test_sign: signature mismatch\nExpected:\n" + self.hexstr(
            signed_tx) + "\n\nActual:\n" + self.hexstr(polly_signed_tx)
Exemplo n.º 15
0
def main():
    parser = argparse.ArgumentParser(
        description=
        "Generate a private wallet key. WARNING: obsolete. Use ku instead.")

    parser.add_argument('-a',
                        "--address",
                        help='show as Bitcoin address',
                        action='store_true')
    parser.add_argument('-i',
                        "--info",
                        help='show metadata',
                        action='store_true')
    parser.add_argument('-j',
                        "--json",
                        help='output metadata as JSON',
                        action='store_true')
    parser.add_argument('-w',
                        "--wif",
                        help='show as Bitcoin WIF',
                        action='store_true')
    parser.add_argument('-f',
                        "--wallet-key-file",
                        help='initial wallet key',
                        type=argparse.FileType('r'))
    parser.add_argument('-k', "--wallet-key", help='initial wallet key')
    parser.add_argument('-g',
                        "--gpg",
                        help='use gpg --gen-random to get additional entropy',
                        action='store_true')
    parser.add_argument('-u',
                        "--dev-random",
                        help='use /dev/random to get additional entropy',
                        action='store_true')
    parser.add_argument('-n',
                        "--uncompressed",
                        help='show in uncompressed form',
                        action='store_true')
    parser.add_argument(
        '-p',
        help='generate wallet key from passphrase. NOT RECOMMENDED',
        metavar='passphrase')
    parser.add_argument('-s', "--subkey", help='subkey path (example: 0p/2/1)')
    parser.add_argument('-t', help='generate test key', action="store_true")
    parser.add_argument('inputfile',
                        help='source of entropy. stdin by default',
                        type=argparse.FileType(mode='r+b'),
                        nargs='?')
    args = parser.parse_args()

    # args.inputfile doesn't like binary when "-" is passed in. Deal with this.
    if args.inputfile == sys.stdin and hasattr(sys.stdin, "buffer"):
        args.inputfile = sys.stdin.buffer

    network = 'XTN' if args.t else 'BTC'

    entropy = bytearray()
    if args.gpg:
        entropy.extend(gpg_entropy())
    if args.dev_random:
        entropy.extend(dev_random_entropy())
    if args.inputfile:
        entropy.extend(args.inputfile.read())
    if args.p:
        entropy.extend(args.p.encode("utf8"))
    if len(entropy) == 0 and not args.wallet_key and not args.wallet_key_file:
        parser.error("you must specify at least one source of entropy")
    if args.wallet_key and len(entropy) > 0:
        parser.error("don't specify both entropy and a wallet key")
    if args.wallet_key_file:
        wallet = Wallet.from_wallet_key(args.wallet_key_file.readline()[:-1])
    elif args.wallet_key:
        wallet = Wallet.from_wallet_key(args.wallet_key)
    else:
        wallet = Wallet.from_master_secret(bytes(entropy), netcode=network)
    try:
        if args.subkey:
            wallet = wallet.subkey_for_path(args.subkey)
        if wallet.child_number >= 0x80000000:
            wc = wallet.child_number - 0x80000000
            child_index = "%dp (%d)" % (wc, wallet.child_number)
        else:
            child_index = "%d" % wallet.child_number
        if args.json:
            d = dict(
                wallet_key=wallet.wallet_key(as_private=wallet.is_private),
                public_pair_x=wallet.public_pair[0],
                public_pair_y=wallet.public_pair[1],
                tree_depth=wallet.depth,
                fingerprint=b2h(wallet.fingerprint()),
                parent_fingerprint=b2h(wallet.parent_fingerprint),
                child_index=child_index,
                chain_code=b2h(wallet.chain_code),
                bitcoin_addr=wallet.bitcoin_address(),
                bitcoin_addr_uncompressed=wallet.bitcoin_address(
                    compressed=False),
                network="test" if wallet.is_test else "main",
            )
            if wallet.is_private:
                d.update(
                    dict(key="private",
                         secret_exponent=wallet.secret_exponent,
                         WIF=wallet.wif(),
                         WIF_uncompressed=wallet.wif(compressed=False)))
            else:
                d.update(dict(key="public"))
            print(json.dumps(d, indent=3))
        elif args.info:
            print(wallet.wallet_key(as_private=wallet.is_private))
            print(full_network_name_for_netcode(wallet.netcode))
            if wallet.is_private:
                print("private key")
                print("secret exponent: %d" % wallet.secret_exponent)
            else:
                print("public key only")
            print("public pair x:   %d\npublic pair y:   %d" %
                  wallet.public_pair)
            print("tree depth:      %d" % wallet.depth)
            print("fingerprint:     %s" % b2h(wallet.fingerprint()))
            print("parent f'print:  %s" % b2h(wallet.parent_fingerprint))
            print("child index:     %s" % child_index)
            print("chain code:      %s" % b2h(wallet.chain_code))
            if wallet.is_private:
                print("WIF:             %s" % wallet.wif())
                print("  uncompressed:  %s" % wallet.wif(compressed=False))
            print("Bitcoin address: %s" % wallet.bitcoin_address())
            print("  uncompressed:  %s" %
                  wallet.bitcoin_address(compressed=False))
        elif args.address:
            print(wallet.bitcoin_address(compressed=not args.uncompressed))
        elif args.wif:
            print(wallet.wif(compressed=not args.uncompressed))
        else:
            print(wallet.wallet_key(as_private=wallet.is_private))
    except PublicPrivateMismatchError as ex:
        print(ex.args[0])
Exemplo n.º 16
0
#!/usr/bin/python
import os

from pycoin.key.bip32 import Wallet
from pycoin.encoding import public_pair_to_hash160_sec, hash160_sec_to_bitcoin_address
from pycoin.networks import address_prefix_for_netcode, alternate_hash_for_netcode
from binascii import hexlify
import bitcoinrpc
import socket

secret = os.urandom(64)
wallet = Wallet.from_master_secret(bytes(secret), 'BLC')

sec = public_pair_to_hash160_sec(wallet.public_pair)
pubkey = ''.join('{:02x}'.format(ord(x)) for x in sec)

addr_blc = hash160_sec_to_bitcoin_address(
    sec,
    address_prefix=address_prefix_for_netcode('BLC'),
    internal_hash=alternate_hash_for_netcode('BLC'))
addr_pho = hash160_sec_to_bitcoin_address(
    sec,
    address_prefix=address_prefix_for_netcode('PHO'),
    internal_hash=alternate_hash_for_netcode('PHO'))
addr_bbtc = hash160_sec_to_bitcoin_address(
    sec,
    address_prefix=address_prefix_for_netcode('BBTC'),
    internal_hash=alternate_hash_for_netcode('BBTC'))
addr_xdq = hash160_sec_to_bitcoin_address(
    sec,
    address_prefix=address_prefix_for_netcode('XDQ'),
Exemplo n.º 17
0
    def test_ref_bip32(self):
        """
        Performs a test of the reference wallet's BIP32 key generation capability.
        """
        
        # BIP32 test vectors, see https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#Test_Vectors
        
        # Vector 1
        
        m = Wallet.from_master_secret(bytes.fromhex("000102030405060708090a0b0c0d0e0f"))
        
        assert m.wallet_key()                                     == "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
        assert m.wallet_key(as_private=True)                      == "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"
        assert m.bitcoin_address()                                == "15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma"
        assert m.wif()                                            == "L52XzL2cMkHxqxBXRyEpnPQZGUs3uKiL3R11XbAdHigRzDozKZeW"

        m0h = m.subkey(is_hardened=True)
        assert m0h.wallet_key()                                   == "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"
        assert m0h.wallet_key(as_private=True)                    == "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7"

        m0h1 = m0h.subkey(i=1)
        assert m0h1.wallet_key()                                  == "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"
        assert m0h1.wallet_key(as_private=True)                   == "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs"

        m0h1_1_2h = m0h1.subkey(i=2, is_hardened=True)
        assert m0h1_1_2h.wallet_key()                             == "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5"
        assert m0h1_1_2h.wallet_key(as_private=True)              == "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM"

        m0h1_1_2h_2 = m0h1_1_2h.subkey(i=2)
        assert m0h1_1_2h_2.wallet_key()                           == "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"
        assert m0h1_1_2h_2.wallet_key(as_private=True)            == "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334"

        m0h1_1_2h_2_1000000000 = m0h1_1_2h_2.subkey(i=1000000000)
        assert m0h1_1_2h_2_1000000000.wallet_key()                == "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"
        assert m0h1_1_2h_2_1000000000.wallet_key(as_private=True) == "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76"

        
        # Vector 2
        
        m = Wallet.from_master_secret(bytes.fromhex("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"))
        
        assert m.wallet_key()                                             == "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"
        assert m.wallet_key(as_private=True)                              == "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U"

        m0 = m.subkey()
        assert m0.wallet_key()                                            == "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"
        assert m0.wallet_key(as_private=True)                             == "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt"

        m0_2147483647p = m0.subkey(i=2147483647, is_hardened=True)
        assert m0_2147483647p.wallet_key()                                == "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a"
        assert m0_2147483647p.wallet_key(as_private=True)                 == "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9"

        m0_2147483647p_1 = m0_2147483647p.subkey(i=1)
        assert m0_2147483647p_1.wallet_key()                              == "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon"
        assert m0_2147483647p_1.wallet_key(as_private=True)               == "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef"

        m0_2147483647p_1_2147483646p = m0_2147483647p_1.subkey(i=2147483646, is_hardened=True)
        assert m0_2147483647p_1_2147483646p.wallet_key()                  == "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"
        assert m0_2147483647p_1_2147483646p.wallet_key(as_private=True)   == "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc"

        m0_2147483647p_1_2147483646p_2 = m0_2147483647p_1_2147483646p.subkey(i=2)
        assert m0_2147483647p_1_2147483646p_2.wallet_key()                == "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"
        assert m0_2147483647p_1_2147483646p_2.wallet_key(as_private=True) == "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j"