예제 #1
0
def search(target_xfp):
    k = BIP32Node.from_hwif(
        "tprv8ZgxMBicQKsPeXJHL3vPPgTAEqQ5P2FD9qDeCQT4Cp1EMY5QkwMPWFxHdxHrxZhhcVRJ2m7BNWTz9Xre68y7mX5vCdMJ5qXMUfnrZ2si2X4"
    )

    pid = os.getpid()
    target_xfp = h2b_rev(target_xfp)

    # test by going -33 here.
    #sec_exp = k._secret_exponent - 33
    sec_exp = k._secret_exponent + (pid * int(1e40))

    i = 0
    last_xfp = None
    while 1:
        i += 1
        sec_exp += 1

        public_pair = ecdsa.public_pair_for_secret_exponent(
            ecdsa.generator_secp256k1, sec_exp)

        xfp = public_pair_to_hash160_sec(public_pair, compressed=True)[:4]

        if i <= 5:
            # checking code (slow)
            b = BIP32Node(netcode='BTC',
                          chain_code=bytes(32),
                          secret_exponent=sec_exp)
            chk = b.fingerprint()
            assert b._secret_exponent == sec_exp
            assert xfp == chk, (xfp, chk)

        assert xfp != last_xfp, 'repeat xfp!'
        last_xfp = xfp

        if xfp == target_xfp:
            print(f"\n\nFOUND: sec_exp = {sec_exp}\n")
            b = BIP32Node(netcode='BTC',
                          chain_code=bytes(32),
                          secret_exponent=sec_exp)
            chk = b.fingerprint()
            assert b._secret_exponent == sec_exp
            assert xfp == chk, (xfp, chk)
            print(b.hwif(), end='\n\n')
            return

        if not (i % 27):
            print('  %6d %9d' % (pid, i), end='\r')
예제 #2
0
    def __init__(self, colormap, config):
        """Create a deterministic wallet address manager given
        a color map <colormap> and a configuration <config>.
        Note address manager configuration is in the key "hdwam".
        """
        self.config = config
        self.testnet = config.get('testnet', False)
        self.colormap = colormap
        self.addresses = []

        # initialize the wallet manager if this is the first time
        #  this will generate a master key.
        params = config.get('hdwam', None)
        if params is None:
            params = self.init_new_wallet()

        # master key is stored in a separate config entry
        self.master_key = config['hdw_master_key']
        master = hashlib.sha512(self.master_key.decode('hex')).digest()
        self.pycoin_wallet = BIP32Node(netcode='BTC',
                                       chain_code=master[32:],
                                       secret_exponent=from_bytes_32(
                                           master[:32]))

        self.genesis_color_sets = params['genesis_color_sets']
        self.color_set_states = params['color_set_states']

        # import the genesis addresses
        for i, color_desc_list in enumerate(self.genesis_color_sets):
            addr = self.get_genesis_address(i)
            addr.color_set = ColorSet(self.colormap, color_desc_list)
            self.addresses.append(addr)

        # now import the specific color addresses
        for color_set_st in self.color_set_states:
            color_desc_list = color_set_st['color_set']
            max_index = color_set_st['max_index']
            color_set = ColorSet(self.colormap, color_desc_list)
            params = {
                'testnet': self.testnet,
                'pycoin_wallet': self.pycoin_wallet,
                'color_set': color_set
            }
            for index in xrange(max_index + 1):
                params['index'] = index
                self.addresses.append(BIP0032AddressRecord(**params))

        # import the one-off addresses from the config
        for addr_params in config.get('addresses', []):
            addr_params['testnet'] = self.testnet
            addr_params['color_set'] = ColorSet(self.colormap,
                                                addr_params['color_set'])
            address = LooseAddressRecord(**addr_params)
            self.addresses.append(address)
예제 #3
0
def nano_get_pub_wallet(path, netcode='BTC'):
    """
    get bip32 wallet with derivable public master key
    :param path: derivation path
    :param netcode: BTC for main net
    :return: wallet string in xpub.... format
    """
    _, depth = parse_bip32_path(path)
    public_key, _, chain_code = nano_get_key(
        path, key_part_pub_key + key_part_chaincode)
    wallet = BIP32Node(netcode,
                       chain_code,
                       depth,
                       public_pair=Key.from_sec(public_key,
                                                netcode).public_pair())
    return wallet.wallet_key(as_private=False)
예제 #4
0
def nano_get_priv_wallet(path, netcode='BTC'):
    """
    get bip32 wallet with derivable private master key
    :param path: derivation path
    :param netcode: BTC for main net
    :return: wallet string in xprv.... format
    """
    _, depth = parse_bip32_path(path)
    _, private_key, chain_code = nano_get_key(
        path, key_part_priv_key + key_part_chaincode)
    bip32_wallet = BIP32Node(
        netcode,
        chain_code,
        depth,
        secret_exponent=encoding.from_bytes_32(private_key))
    return bip32_wallet.wallet_key(as_private=True)
예제 #5
0
    def test_key_limits(self):
        nc = 'BTC'
        cc = b'000102030405060708090a0b0c0d0e0f'
        order = generator_secp256k1.order()

        for k in -1, 0, order, order + 1:
            self.assertRaises(InvalidSecretExponentError,
                              Key,
                              secret_exponent=k)
            self.assertRaises(InvalidSecretExponentError,
                              BIP32Node,
                              nc,
                              cc,
                              secret_exponent=k)

        for i in range(1, 512):
            Key(secret_exponent=i)
            BIP32Node(nc, cc, secret_exponent=i)
예제 #6
0
파일: app.py 프로젝트: sahabi/keyman
    def start_second(self):
        self.ui = Ui_second()
        self.ui.setupUi(self.second)
        master_node = BIP32Node(self.netcode,
                                self.chain_code,
                                secret_exponent=int(self.secret_exponent, 16))
        master_pub_node = master_node.public_copy()
        privkey_tree_item = PrivKeyTreeWidgetItem(key_type='Private Key',
                                                  level='m',
                                                  key=master_node)
        pubkey_tree_item = PubKeyTreeWidgetItem(key_type='Public Key',
                                                level='M',
                                                key=master_pub_node)

        self.privkeychain.append(privkey_tree_item)
        self.pubkeychain.append(pubkey_tree_item)
        self.ui.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.ui.treeWidget.customContextMenuRequested.connect(
            self.show_context_menu)
        self.ui.treeWidget.addTopLevelItems(
            [privkey_tree_item, pubkey_tree_item])
        self.second.show()
예제 #7
0
def test_bitcoind_cosigning(dev, bitcoind, start_sign, end_sign, import_ms_wallet, clear_ms, explora, try_sign, need_keypress, addr_style):
    # Make a P2SH wallet with local bitcoind as a co-signer (and simulator)
    # - send an receive various
    # - following text of <https://github.com/bitcoin/bitcoin/blob/master/doc/psbt.md>
    # - the constructed multisig walelt will only work for a single pubkey on core side
    # - before starting this test, have some funds already deposited to bitcoind testnet wallet
    from pycoin.encoding import sec_to_public_pair
    from binascii import a2b_hex
    import re

    if addr_style == 'legacy':
        addr_fmt = AF_P2SH
    elif addr_style == 'p2sh-segwit':
        addr_fmt = AF_P2WSH_P2SH
    elif addr_style == 'bech32':
        addr_fmt = AF_P2WSH
    
    try:
        addr, = bitcoind.getaddressesbylabel("sim-cosign").keys()
    except:
        addr = bitcoind.getnewaddress("sim-cosign")

    info = bitcoind.getaddressinfo(addr)
    #pprint(info)

    assert info['address'] == addr
    bc_xfp = swab32(int(info['hdmasterfingerprint'], 16))
    bc_deriv = info['hdkeypath']        # example: "m/0'/0'/3'"
    bc_pubkey = info['pubkey']          # 02f75ae81199559c4aa...

    pp = sec_to_public_pair(a2b_hex(bc_pubkey))

    # No means to export XPUB from bitcoind! Still. In 2019.
    # - this fake will only work for for one pubkey value, the first/topmost
    node = BIP32Node('XTN', b'\x23'*32, depth=len(bc_deriv.split('/'))-1,
                        parent_fingerprint=a2b_hex('%08x' % bc_xfp), public_pair=pp)

    keys = [
        (bc_xfp, None, node),
        (1130956047, None, BIP32Node.from_hwif('tpubD8NXmKsmWp3a3DXhbihAYbYLGaRNVdTnr6JoSxxfXYQcmwVtW2hv8QoDwng6JtEonmJoL3cNEwfd2cLXMpGezwZ2vL2dQ7259bueNKj9C8n')),     # simulator: m/45'
    ]

    M,N=2,2

    clear_ms()
    import_ms_wallet(M, N, keys=keys, accept=1, name="core-cosign")

    cc_deriv = "m/45'/55"
    cc_pubkey = B2A(BIP32Node.from_hwif(simulator_fixed_xprv).subkey_for_path(cc_deriv[2:]).sec())

    

    # NOTE: bitcoind doesn't seem to implement pubkey sorting. We have to do it.
    resp = bitcoind.addmultisigaddress(M, list(sorted([cc_pubkey, bc_pubkey])),
                                                'shared-addr-'+addr_style, addr_style)
    ms_addr = resp['address']
    bc_redeem = a2b_hex(resp['redeemScript'])

    assert bc_redeem[0] == 0x52

    def mapper(cosigner_idx):
        return list(str2ipath(cc_deriv if cosigner_idx else bc_deriv))

    scr, pubkeys, xfp_paths = make_redeem(M, keys, mapper)

    assert scr == bc_redeem

    # check Coldcard calcs right address to match
    got_addr = dev.send_recv(CCProtocolPacker.show_p2sh_address(
                                M, xfp_paths, scr, addr_fmt=addr_fmt), timeout=None)
    assert got_addr == ms_addr
    time.sleep(.1)
    need_keypress('x')      # clear screen / start over

    print(f"Will be signing an input from {ms_addr}")

    if xfp2str(bc_xfp) in ('5380D0ED', 'EDD08053'):
        # my own expected values
        assert ms_addr in ( '2NDT3ymKZc8iMfbWqsNd1kmZckcuhixT5U4',
                            '2N1hZJ5mazTX524GQTPKkCT4UFZn5Fqwdz6',
                            'tb1qpcv2rkc003p5v8lrglrr6lhz2jg8g4qa9vgtrgkt0p5rteae5xtqn6njw9')

    # Need some UTXO to sign
    #
    # - but bitcoind can't give me that (using listunspent) because it's only a watched addr??
    #
    did_fund = False
    while 1:
        rr = explora('address', ms_addr, 'utxo')
        pprint(rr)

        avail = []
        amt = 0
        for i in rr:
            txn = i['txid']
            vout = i['vout']
            avail.append( (txn, vout) )
            amt += i['value']

            # just use first UTXO available; save other for later tests
            break

        else:
            # doesn't need to confirm, but does need to reach public testnet/blockstream
            assert not amt and not avail

            if not did_fund:
                print(f"Sending some XTN to {ms_addr}  (wait)")
                bitcoind.sendtoaddress(ms_addr, 0.0001, 'fund testing')
                did_fund = True
            else:
                print(f"Still waiting ...")

            time.sleep(2)

        if amt: break

    ret_addr = bitcoind.getrawchangeaddress()

    ''' If you get insufficent funds, even tho we provide the UTXO (!!), do this:

            bitcoin-cli importaddress "2NDT3ymKZc8iMfbWqsNd1kmZckcuhixT5U4" true true

        Better method: always fund addresses for testing here from same wallet (ie.
        got from non-multisig to multisig on same bitcoin-qt instance).
        -> Now doing that, automated, above.
    '''
    resp = bitcoind.walletcreatefundedpsbt([dict(txid=t, vout=o) for t,o in avail],
               [{ret_addr: amt/1E8}], 0,
                {'subtractFeeFromOutputs': [0], 'includeWatching': True}, True)

    assert resp['changepos'] == -1
    psbt = b64decode(resp['psbt'])

    open('debug/funded.psbt', 'wb').write(psbt)

    # patch up the PSBT a little ... bitcoind doesn't know the path for the CC's key
    ex = BasicPSBT().parse(psbt)
    cxpk = a2b_hex(cc_pubkey)
    for i in ex.inputs:
        assert cxpk in i.bip32_paths, 'input not to be signed by CC?'
        i.bip32_paths[cxpk] = pack('<3I', keys[1][0], *str2ipath(cc_deriv))

    psbt = ex.as_bytes()

    open('debug/patched.psbt', 'wb').write(psbt)

    _, updated = try_sign(psbt, finalize=False)

    open('debug/cc-updated.psbt', 'wb').write(updated)

    # have bitcoind do the rest of the signing
    rr = bitcoind.walletprocesspsbt(b64encode(updated).decode('ascii'))
    pprint(rr)

    open('debug/bc-processed.psbt', 'wt').write(rr['psbt'])
    assert rr['complete']

    # finalize and send
    rr = bitcoind.finalizepsbt(rr['psbt'], True)
    open('debug/bc-final-txn.txn', 'wt').write(rr['hex'])
    assert rr['complete']

    txn_id = bitcoind.sendrawtransaction(rr['hex'])
    print(txn_id)
예제 #8
0
파일: bip32_test.py 프로젝트: stafur/pycoin
def Wallet(*args, **kwargs):
    return BIP32Node(*args, **kwargs)