示例#1
0
 def setUp(self):
     self.n = 2
     #create n new random wallets.
     #put coins into the first mixdepth for each
     #The amount is 1btc + 300,000 satoshis, to account
     #for a 0.2% fee for 1 counterparty + a large tx fee.
     #(but not large enough to handle the bad wallet)
     wallet_structures = [[1, 0, 0, 0, 0]] * (self.n)
     self.wallets = make_wallets(self.n,
                                 wallet_structures=wallet_structures,
                                 mean_amt=1.00300000)
     #the sender is wallet (n), i.e. index wallets[n-1]
     #we need a counterparty with a huge set of utxos.
     bad_wallet_struct = [[1, 0, 0, 0, 0]]
     self.wallets.update(
         make_wallets(1,
                      wallet_structures=bad_wallet_struct,
                      mean_amt=0.01,
                      start_index=2))
     #having created the bad wallet, add lots of utxos to
     #the same mixdepth
     print 'creating a crazy amount of utxos in one wallet...'
     r_addr = self.wallets[2]['wallet'].get_external_addr(0)
     for i in range(60):
         jm_single().bc_interface.grab_coins(r_addr, 0.02)
         time.sleep(1)
     #for sweep, create a yg wallet with enough for the mix
     #of the bad wallet above (acting as sender)
     self.wallets.update(
         make_wallets(1,
                      wallet_structures=[[1, 0, 0, 0, 0]],
                      mean_amt=3,
                      start_index=3))
示例#2
0
def make_tx_add_notify():
    wallet_dict = make_wallets(1, [[1, 0, 0, 0, 0]], mean_amt=4, sdev_amt=0)[0]
    amount = 250000000
    txfee = 10000
    wallet = wallet_dict['wallet']
    sync_wallet(wallet)
    inputs = wallet.select_utxos(0, amount)
    ins = inputs.keys()
    input_value = sum([i['value'] for i in inputs.values()])
    output_addr = wallet.get_new_addr(1, 0)
    change_addr = wallet.get_new_addr(0, 1)
    outs = [{
        'value': amount,
        'address': output_addr
    }, {
        'value': input_value - amount - txfee,
        'address': change_addr
    }]
    tx = btc.mktx(ins, outs)
    de_tx = btc.deserialize(tx)
    for index, ins in enumerate(de_tx['ins']):
        utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index'])
        addr = inputs[utxo]['address']
        priv = wallet.get_key_from_addr(addr)
        tx = btc.sign(tx, index, priv)

    unconfirm_called[0] = confirm_called[0] = False
    timeout_unconfirm_called[0] = timeout_confirm_called[0] = False
    jm_single().bc_interface.add_tx_notify(btc.deserialize(tx),
                                           unconfirm_callback,
                                           confirm_callback, output_addr,
                                           timeout_callback)
    return tx
示例#3
0
def test_wallet_sync_from_scratch(setup_wallets, wallet_structure,
                                  wallet_file, password, ic):
    """Simulate a scenario in which we use a new bitcoind, thusly:
    generate a new wallet and simply pretend that it has an existing
    index_cache. This will force import of all addresses up to
    the index_cache values.
    """
    setup_import(mainnet=False)
    wallet = make_wallets(1,[wallet_structure],
                              fixed_seeds=[wallet_file],
                              test_wallet=True, passwords=[password])[0]['wallet']
    sync_count = 0
    jm_single().bc_interface.wallet_synced = False
    wallet.index_cache = ic
    while not jm_single().bc_interface.wallet_synced:
        wallet.index = []
        for i in range(5):
            wallet.index.append([0, 0])
        jm_single().bc_interface.sync_wallet(wallet)
        sync_count += 1
        #avoid infinite loop
        assert sync_count < 10
        log.debug("Tried " + str(sync_count) + " times")
    #after #586 we expect to ALWAYS succeed within 2 rounds
    assert sync_count == 2
    #for each external branch, the new index may be higher than
    #the original index_cache if there was a higher used address
    expected_wallet_index = []
    for i, val in enumerate(wallet_structure):
        if val > wallet.index_cache[i][0]:
            expected_wallet_index.append([val, wallet.index_cache[i][1]])
        else:
            expected_wallet_index.append([wallet.index_cache[i][0],
                                          wallet.index_cache[i][1]])
    assert wallet.index == expected_wallet_index
示例#4
0
def test_broadcast_self(setup_tx_notify):
    cjtx = create_testing_cjtx(['counterparty'])
    jm_single().config.set('POLICY', 'tx_broadcast', 'self')
    cjtx.push()
    assert self_pushtx_count[0] == 1
    assert sum(msgchan_pushtx_count[0].values()) == 0
    return True
示例#5
0
def main():
    jm_single().nickname = random_nick(
    )  # watcher' +binascii.hexlify(os.urandom(4))
    load_program_config()

    parser = OptionParser(
        usage='usage: %prog [options]',
        description='Runs a webservice which shows the orderbook.')
    parser.add_option('-H',
                      '--host',
                      action='store',
                      type='string',
                      dest='host',
                      default='localhost',
                      help='hostname or IP to bind to, default=localhost')
    parser.add_option('-p',
                      '--port',
                      action='store',
                      type='int',
                      dest='port',
                      help='port to listen on, default=62601',
                      default=62601)
    (options, args) = parser.parse_args()

    hostport = (options.host, options.port)

    irc = IRCMessageChannel(jm_single().nickname)

    # todo: is the call to GUITaker needed, or the return. taker unused
    taker = GUITaker(irc, hostport)
    print('starting irc')

    irc.run()
示例#6
0
def main():
    jm_single().nickname = random_nick()  # watcher' +binascii.hexlify(os.urandom(4))
    load_program_config()

    parser = OptionParser(
            usage='usage: %prog [options]',
            description='Runs a webservice which shows the orderbook.')
    parser.add_option('-H',
                      '--host',
                      action='store',
                      type='string',
                      dest='host',
                      default='localhost',
                      help='hostname or IP to bind to, default=localhost')
    parser.add_option('-p',
                      '--port',
                      action='store',
                      type='int',
                      dest='port',
                      help='port to listen on, default=62601',
                      default=62601)
    (options, args) = parser.parse_args()

    hostport = (options.host, options.port)

    irc = IRCMessageChannel(jm_single().nickname)

    # todo: is the call to GUITaker needed, or the return. taker unused
    taker = GUITaker(irc, hostport)
    print('starting irc')

    irc.run()
示例#7
0
def test_start_ygs(setup_ygrunner, num_ygs, wallet_structures, mean_amt):
    """Set up some wallets, for the ygs and 1 sp.
    Then start the ygs in background and publish
    the seed of the sp wallet for easy import into -qt
    """
    wallets = make_wallets(num_ygs + 1,
                           wallet_structures=wallet_structures,
                           mean_amt=mean_amt)
    #the sendpayment bot uses the last wallet in the list
    wallet = wallets[num_ygs]['wallet']
    print "Seed : " + wallets[num_ygs]['seed']
    #useful to see the utxos on screen sometimes
    jm_single().bc_interface.sync_wallet(wallet)
    print wallet.unspent

    yigen_procs = []
    for i in range(num_ygs):
        ygp = local_command([python_cmd, yg_cmd,\
                             str(wallets[i]['seed'])], bg=True)
        time.sleep(2)  #give it a chance
        yigen_procs.append(ygp)
    try:
        while True:
            time.sleep(20)
            print 'waiting'
    finally:
        if any(yigen_procs):
            for ygp in yigen_procs:
                #NB *GENTLE* shutdown is essential for
                #test coverage reporting!
                ygp.send_signal(signal.SIGINT)
                ygp.wait()
示例#8
0
 def init_tx(self, tx, balance, sweep):
     destaddr = None
     if tx['destination'] == 'internal':
         destaddr = self.taker.wallet.get_internal_addr(tx['srcmixdepth'] +
                                                        1)
     elif tx['destination'] == 'addrask':
         jm_single().debug_silence[0] = True
         while True:
             destaddr = raw_input('insert new address: ')
             addr_valid, errormsg = validate_address(destaddr)
             if addr_valid:
                 break
             print('Address ' + destaddr + ' invalid. ' + errormsg +
                   ' try again')
         jm_single().debug_silence[0] = False
     else:
         destaddr = tx['destination']
     self.taker.wallet.update_cache_index()
     self.sweep = sweep
     self.balance = balance
     self.tx = tx
     self.destaddr = destaddr
     self.create_tx_attempts = self.taker.options.maxcreatetx
     self.create_tx()
     with self.lockcond:
         self.lockcond.wait()
     log.debug('tx confirmed, waiting for ' + str(tx['wait']) + ' minutes')
     time.sleep(tx['wait'] * 60)
     log.debug('woken')
示例#9
0
 def setUp(self):
     self.n = 2
     #create n new random wallets.
     #put coins into the first mixdepth for each
     #The amount is 1btc + 300,000 satoshis, to account
     #for a 0.2% fee for 1 counterparty + a large tx fee.
     #(but not large enough to handle the bad wallet)
     wallet_structures = [[1, 0, 0, 0, 0]] * (self.n)
     self.wallets = make_wallets(self.n,
                                 wallet_structures=wallet_structures,
                                 mean_amt=1.00300000)
     #the sender is wallet (n), i.e. index wallets[n-1]
     #we need a counterparty with a huge set of utxos.
     bad_wallet_struct = [[1, 0, 0, 0, 0]]
     self.wallets.update(make_wallets(1,
                                      wallet_structures=bad_wallet_struct,
                                      mean_amt=0.01,
                                      start_index=2))
     #having created the bad wallet, add lots of utxos to 
     #the same mixdepth
     print 'creating a crazy amount of utxos in one wallet...'
     r_addr = self.wallets[2]['wallet'].get_external_addr(0)
     for i in range(60):
         jm_single().bc_interface.grab_coins(r_addr, 0.02)
         time.sleep(1)
     #for sweep, create a yg wallet with enough for the mix
     #of the bad wallet above (acting as sender)
     self.wallets.update(make_wallets(1,
                                      wallet_structures=[[1, 0, 0, 0, 0]],
                                      mean_amt=3,
                                      start_index=3))
示例#10
0
def test_utxo_selection(setup_wallets, nw, wallet_structures, mean_amt,
                        sdev_amt, amount):
    """Check that all the utxo selection algorithms work with a random
    variety of wallet contents.
    """
    wallets = make_wallets(nw, wallet_structures, mean_amt, sdev_amt)
    for w in wallets.values():
        jm_single().bc_interface.wallet_synced = False
        jm_single().bc_interface.sync_wallet(w['wallet'])
    for k, w in enumerate(wallets.values()):
        for algo in [select_gradual, select_greedy, select_greediest, None]:
            wallet = w['wallet']
            if algo:
                wallet.utxo_selector = algo
            if k == 0:
                with pytest.raises(Exception) as e_info:
                    selected = wallet.select_utxos(1, amount)
            else:
                selected = wallet.select_utxos(1, amount)
                algostr = algo.__name__ if algo else "default"
                print 'selected these for algo ' + algostr + ':'
                print selected
                #basic check:
                #does this algo actually generate sufficient coins?
                total_selected = sum([x['value'] for x in selected.values()])
                assert total_selected > amount, "Selection algo: " + algo + \
                       "failed to select sufficient coins, total: " + \
                       str(total_selected) + ", should be: " + str(amount)
示例#11
0
 def init_tx(self, tx, balance, sweep):
     destaddr = None
     if tx['destination'] == 'internal':
         destaddr = self.taker.wallet.get_internal_addr(tx['srcmixdepth'] + 1)
     elif tx['destination'] == 'addrask':
         jm_single().debug_silence[0] = True
         print('\n'.join(['=' * 60] * 3))
         print('Tumbler requires more addresses to stop amount correlation')
         print('Obtain a new destination address from your bitcoin recipient')
         print(' for example click the button that gives a new deposit address')
         print('\n'.join(['=' * 60] * 1))
         while True:
             destaddr = raw_input('insert new address: ')
             addr_valid, errormsg = validate_address(destaddr)
             if addr_valid:
                 break
             print(
             'Address ' + destaddr + ' invalid. ' + errormsg + ' try again')
         jm_single().debug_silence[0] = False
     else:
         destaddr = tx['destination']
     self.taker.wallet.update_cache_index()
     self.sweep = sweep
     self.balance = balance
     self.tx = tx
     self.destaddr = destaddr
     self.create_tx_attempts = self.taker.options['maxcreatetx']
     self.create_tx()
     with self.lockcond:
         self.lockcond.wait()
     log.debug('tx confirmed, waiting for ' + str(tx['wait']) + ' minutes')
     time.sleep(tx['wait'] * 60)
     log.debug('woken')
示例#12
0
def make_wallets(n,
                 wallet_structures=None,
                 mean_amt=1,
                 sdev_amt=0,
                 start_index=0):
    '''n: number of wallets to be created
       wallet_structure: array of n arrays , each subarray
       specifying the number of addresses to be populated with coins
       at each depth (for now, this will only populate coins into 'receive' addresses)
       mean_amt: the number of coins (in btc units) in each address as above
       sdev_amt: if randomness in amouts is desired, specify here.
       Returns: a dict of dicts of form {0:{'seed':seed,'wallet':Wallet object},1:..,}'''
    if len(wallet_structures) != n:
        raise Exception("Number of wallets doesn't match wallet structures")
    seeds = chunks(binascii.hexlify(os.urandom(15 * n)), n)
    wallets = {}
    for i in range(n):
        wallets[i + start_index] = {
            'seed': seeds[i],
            'wallet': Wallet(seeds[i], max_mix_depth=5)
        }
        for j in range(5):
            for k in range(wallet_structures[i][j]):
                deviation = sdev_amt * random.random()
                amt = mean_amt - sdev_amt / 2.0 + deviation
                if amt < 0: amt = 0.001
                jm_single().bc_interface.grab_coins(
                    wallets[i + start_index]['wallet'].get_external_addr(j),
                    amt)
    return wallets
    def oid_to_order(self, cjorder, oid, amount):
        total_amount = amount + cjorder.txfee
        mix_balance = self.wallet.get_balance_by_mixdepth()
        max_mix = max(mix_balance, key=mix_balance.get)

        filtered_mix_balance = [m
                                for m in mix_balance.iteritems()
                                if m[1] >= total_amount]
        log.debug('mix depths that have enough = ' + str(filtered_mix_balance))
        filtered_mix_balance = sorted(filtered_mix_balance, key=lambda x: x[0])
        mixdepth = filtered_mix_balance[0][0]
        log.debug('filling offer, mixdepth=' + str(mixdepth))

        # mixdepth is the chosen depth we'll be spending from
        cj_addr = self.wallet.get_internal_addr((mixdepth + 1) %
                                                self.wallet.max_mix_depth)
        change_addr = self.wallet.get_internal_addr(mixdepth)

        utxos = self.wallet.select_utxos(mixdepth, total_amount)
        my_total_in = sum([va['value'] for va in utxos.values()])
        real_cjfee = calc_cj_fee(cjorder.ordertype, cjorder.cjfee, amount)
        change_value = my_total_in - amount - cjorder.txfee + real_cjfee
        if change_value <= jm_single().DUST_THRESHOLD:
            log.debug(('change value={} below dust threshold, '
                       'finding new utxos').format(change_value))
            try:
                utxos = self.wallet.select_utxos(
                    mixdepth, total_amount + jm_single().DUST_THRESHOLD)
            except Exception:
                log.debug('dont have the required UTXOs to make a '
                          'output above the dust threshold, quitting')
                return None, None, None

        return utxos, cj_addr, change_addr
示例#14
0
def setup_import(mainnet=True):
    try:
        os.remove("wallets/test_import_wallet.json")
    except:
        pass
    if mainnet:
        jm_single().config.set("BLOCKCHAIN", "network", "mainnet")
    pwd = 'import-pwd'
    test_in = [pwd, pwd, 'test_import_wallet.json']
    expected = [
        'Enter wallet encryption passphrase:',
        'Reenter wallet encryption passphrase:', 'Input wallet file name'
    ]
    testlog = open('test/testlog-' + pwd, 'wb')
    p = pexpect.spawn('python wallet-tool.py generate', logfile=testlog)
    interact(p, test_in, expected)
    p.expect('saved to')
    time.sleep(1)
    p.close()
    testlog.close()
    #anything to check in the log?
    with open(os.path.join('test', 'testlog-' + pwd)) as f:
        print f.read()
    if p.exitstatus != 0:
        raise Exception('failed due to exit status: ' + str(p.exitstatus))
    jm_single().config.set("BLOCKCHAIN", "network", "testnet")
示例#15
0
def test_broadcast_self(setup_tx_notify):
    cjtx = create_testing_cjtx(['counterparty'])
    jm_single().config.set('POLICY', 'tx_broadcast', 'self')
    cjtx.push()
    assert self_pushtx_count[0] == 1
    assert sum(msgchan_pushtx_count[0].values()) == 0
    return True
示例#16
0
def test_start_ygs(setup_ygrunner, num_ygs, wallet_structures, mean_amt):
    """Set up some wallets, for the ygs and 1 sp.
    Then start the ygs in background and publish
    the seed of the sp wallet for easy import into -qt
    """
    wallets = make_wallets(num_ygs + 1,
                           wallet_structures=wallet_structures,
                           mean_amt=mean_amt)
    #the sendpayment bot uses the last wallet in the list
    wallet = wallets[num_ygs]['wallet']
    print "Seed : " + wallets[num_ygs]['seed']
    #useful to see the utxos on screen sometimes
    jm_single().bc_interface.sync_wallet(wallet)
    print wallet.unspent

    yigen_procs = []
    for i in range(num_ygs):
        ygp = local_command([python_cmd, yg_cmd,\
                             str(wallets[i]['seed'])], bg=True)
        time.sleep(2)  #give it a chance
        yigen_procs.append(ygp)
    try:
        while True:
            time.sleep(20)
            print 'waiting'   
    finally:
        if any(yigen_procs):
            for ygp in yigen_procs:
                #NB *GENTLE* shutdown is essential for
                #test coverage reporting!
                ygp.send_signal(signal.SIGINT)
                ygp.wait()
示例#17
0
def test_create_sighash_txs(setup_tx_creation):
    #non-standard hash codes:
    for sighash in [
            btc.SIGHASH_ANYONECANPAY + btc.SIGHASH_SINGLE, btc.SIGHASH_NONE,
            btc.SIGHASH_SINGLE
    ]:
        wallet = make_wallets(1, [[2, 0, 0, 0, 1]], 3)[0]['wallet']
        jm_single().bc_interface.sync_wallet(wallet)
        amount = 350000000
        ins_full = wallet.select_utxos(0, amount)
        print "using hashcode: " + str(sighash)
        txid = make_sign_and_push(ins_full, wallet, amount, hashcode=sighash)
        assert txid

    #Create an invalid sighash single (too many inputs)
    extra = wallet.select_utxos(4, 100000000)  #just a few more inputs
    ins_full.update(extra)
    with pytest.raises(Exception) as e_info:
        txid = make_sign_and_push(ins_full,
                                  wallet,
                                  amount,
                                  hashcode=btc.SIGHASH_SINGLE)

    #trigger insufficient funds
    with pytest.raises(Exception) as e_info:
        fake_utxos = wallet.select_utxos(4, 1000000000)
示例#18
0
def test_utxo_selection(setup_wallets, nw, wallet_structures, mean_amt,
                        sdev_amt, amount):
    """Check that all the utxo selection algorithms work with a random
    variety of wallet contents.
    """
    wallets = make_wallets(nw, wallet_structures, mean_amt, sdev_amt)
    for w in wallets.values():
        jm_single().bc_interface.wallet_synced = False
        jm_single().bc_interface.sync_wallet(w['wallet'])
    for k, w in enumerate(wallets.values()):
        for algo in [select_gradual, select_greedy, select_greediest, None]:
            wallet = w['wallet']
            if algo:
                wallet.utxo_selector = algo
            if k == 0:
                with pytest.raises(Exception) as e_info:
                    selected = wallet.select_utxos(1, amount)
            else:
                selected = wallet.select_utxos(1, amount)
                algostr = algo.__name__ if algo else "default"
                print 'selected these for algo ' + algostr + ':'
                print selected
                #basic check:
                #does this algo actually generate sufficient coins?
                total_selected = sum([x['value'] for x in selected.values()])
                assert total_selected > amount, "Selection algo: " + algo + \
                       "failed to select sufficient coins, total: " + \
                       str(total_selected) + ", should be: " + str(amount)
示例#19
0
def test_spend_p2sh_utxos(setup_tx_creation):
    #make a multisig address from 3 privs
    privs = [chr(x) * 32 + '\x01' for x in range(1, 4)]
    pubs = [btc.privkey_to_pubkey(binascii.hexlify(priv)) for priv in privs]
    script = btc.mk_multisig_script(pubs, 2)
    msig_addr = btc.scriptaddr(script, magicbyte=196)
    #pay into it
    wallet = make_wallets(1, [[2, 0, 0, 0, 1]], 3)[0]['wallet']
    jm_single().bc_interface.sync_wallet(wallet)
    amount = 350000000
    ins_full = wallet.select_utxos(0, amount)
    txid = make_sign_and_push(ins_full, wallet, amount, output_addr=msig_addr)
    assert txid
    #wait for mining
    time.sleep(4)
    #spend out; the input can be constructed from the txid of previous
    msig_in = txid + ":0"
    ins = [msig_in]
    #random output address and change addr
    output_addr = wallet.get_new_addr(1, 1)
    amount2 = amount - 50000
    outs = [{'value': amount2, 'address': output_addr}]
    tx = btc.mktx(ins, outs)
    sigs = []
    for priv in privs[:2]:
        sigs.append(btc.multisign(tx, 0, script, binascii.hexlify(priv)))
    tx = btc.apply_multisignatures(tx, 0, script, sigs)
    txid = jm_single().bc_interface.pushtx(tx)
    assert txid
示例#20
0
def make_tx_add_notify():
    wallet_dict = make_wallets(1, [[1, 0, 0, 0, 0]], mean_amt=4, sdev_amt=0)[0]
    amount = 250000000
    txfee = 10000
    wallet = wallet_dict['wallet']
    sync_wallet(wallet)
    inputs = wallet.select_utxos(0, amount)
    ins = inputs.keys()
    input_value = sum([i['value'] for i in inputs.values()])
    output_addr = wallet.get_new_addr(1, 0)
    change_addr = wallet.get_new_addr(0, 1)
    outs = [{'value': amount, 'address': output_addr},
            {'value': input_value - amount - txfee, 'address': change_addr}]
    tx = btc.mktx(ins, outs)
    de_tx = btc.deserialize(tx)
    for index, ins in enumerate(de_tx['ins']):
        utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index'])
        addr = inputs[utxo]['address']
        priv = wallet.get_key_from_addr(addr)
        tx = btc.sign(tx, index, priv)

    unconfirm_called[0] = confirm_called[0] = False
    timeout_unconfirm_called[0] = timeout_confirm_called[0] = False
    jm_single().bc_interface.add_tx_notify(
        btc.deserialize(tx), unconfirm_callback,
        confirm_callback, output_addr, timeout_callback)
    return tx
示例#21
0
def test_wif_privkeys_valid(setup_keys):
    with open("test/base58_keys_valid.json", "r") as f:
        json_data = f.read()
    valid_keys_list = json.loads(json_data)
    for a in valid_keys_list:
        key, hex_key, prop_dict = a
        if prop_dict["isPrivkey"]:
            netval = "testnet" if prop_dict["isTestnet"] else "mainnet"
            jm_single().config.set("BLOCKCHAIN", "network", netval)
            print 'testing this key: ' + key
            assert chr(btc.get_version_byte(
                key)) in '\x80\xef', "not valid network byte"
            if "decode_privkey" in dir(btc):
                from_wif_key = btc.decode_privkey(key)
                expected_key = btc.decode_privkey(hex_key)
            else:
                comp = prop_dict["isCompressed"]
                from_wif_key = btc.from_wif_privkey(
                    key,
                    compressed=comp,
                    vbyte=btc.get_version_byte(key)-128)
                expected_key = hex_key
                if comp: expected_key += '01'
            assert from_wif_key == expected_key, "Incorrect key decoding: " + \
                   str(from_wif_key) + ", should be: " + str(expected_key)
示例#22
0
def setup_import(mainnet=True):
    try:
        os.remove("wallets/test_import_wallet.json")
    except:
        pass
    if mainnet:
        jm_single().config.set("BLOCKCHAIN", "network", "mainnet")
    pwd = 'import-pwd'
    test_in = [pwd, pwd, 'test_import_wallet.json']
    expected = ['Enter wallet encryption passphrase:',
                'Reenter wallet encryption passphrase:',
                'Input wallet file name']
    testlog = open('test/testlog-' + pwd, 'wb')
    p = pexpect.spawn('python wallet-tool.py generate', logfile=testlog)
    interact(p, test_in, expected)
    p.expect('saved to')
    time.sleep(1)
    p.close()
    testlog.close()
    #anything to check in the log?
    with open(os.path.join('test', 'testlog-' + pwd)) as f:
        print f.read()
    if p.exitstatus != 0:
        raise Exception('failed due to exit status: ' + str(p.exitstatus))
    jm_single().config.set("BLOCKCHAIN", "network", "testnet")
示例#23
0
def test_wif_privkeys_valid(setup_keys):
    with open("test/base58_keys_valid.json", "r") as f:
        json_data = f.read()
    valid_keys_list = json.loads(json_data)
    for a in valid_keys_list:
        key, hex_key, prop_dict = a
        if prop_dict["isPrivkey"]:
            netval = "testnet" if prop_dict["isTestnet"] else "mainnet"
            jm_single().config.set("BLOCKCHAIN", "network", netval)
            print 'testing this key: ' + key
            assert chr(btc.get_version_byte(
                key)) in '\x80\xef', "not valid network byte"
            if "decode_privkey" in dir(btc):
                from_wif_key = btc.decode_privkey(key)
                expected_key = btc.decode_privkey(hex_key)
            else:
                comp = prop_dict["isCompressed"]
                from_wif_key = btc.from_wif_privkey(
                    key,
                    compressed=comp,
                    vbyte=btc.get_version_byte(key) - 128)
                expected_key = hex_key
                if comp: expected_key += '01'
            assert from_wif_key == expected_key, "Incorrect key decoding: " + \
                   str(from_wif_key) + ", should be: " + str(expected_key)
示例#24
0
    def oid_to_order(self, cjorder, oid, amount):
        total_amount = amount + cjorder.txfee
        mix_balance = self.wallet.get_balance_by_mixdepth()
        max_mix = max(mix_balance, key=mix_balance.get)

        filtered_mix_balance = [
            m for m in mix_balance.iteritems() if m[1] >= total_amount
        ]
        log.debug('mix depths that have enough = ' + str(filtered_mix_balance))
        filtered_mix_balance = sorted(filtered_mix_balance, key=lambda x: x[0])
        mixdepth = filtered_mix_balance[0][0]
        log.debug('filling offer, mixdepth=' + str(mixdepth))

        # mixdepth is the chosen depth we'll be spending from
        cj_addr = self.wallet.get_internal_addr(
            (mixdepth + 1) % self.wallet.max_mix_depth)
        change_addr = self.wallet.get_internal_addr(mixdepth)

        utxos = self.wallet.select_utxos(mixdepth, total_amount)
        my_total_in = sum([va['value'] for va in utxos.values()])
        real_cjfee = calc_cj_fee(cjorder.ordertype, cjorder.cjfee, amount)
        change_value = my_total_in - amount - cjorder.txfee + real_cjfee
        if change_value <= jm_single().DUST_THRESHOLD:
            log.debug(('change value={} below dust threshold, '
                       'finding new utxos').format(change_value))
            try:
                utxos = self.wallet.select_utxos(
                    mixdepth, total_amount + jm_single().DUST_THRESHOLD)
            except Exception:
                log.debug('dont have the required UTXOs to make a '
                          'output above the dust threshold, quitting')
                return None, None, None

        return utxos, cj_addr, change_addr
示例#25
0
 def init_tx(self, tx, balance, sweep):
     destaddr = None
     if tx['destination'] == 'internal':
         destaddr = self.taker.wallet.get_internal_addr(tx['srcmixdepth'] + 1)
     elif tx['destination'] == 'addrask':
         jm_single().debug_silence = True
         while True:
             destaddr = raw_input('insert new address: ')
             addr_valid, errormsg = validate_address(destaddr)
             if addr_valid:
                 break
             print(
             'Address ' + destaddr + ' invalid. ' + errormsg + ' try again')
         jm_single().debug_silence = False
     else:
         destaddr = tx['destination']
     self.sweep = sweep
     self.balance = balance
     self.tx = tx
     self.destaddr = destaddr
     self.create_tx()
     self.lockcond.acquire()
     self.lockcond.wait()
     self.lockcond.release()
     log.debug('tx confirmed, waiting for ' + str(tx['wait']) + ' minutes')
     time.sleep(tx['wait'] * 60)
     log.debug('woken')
示例#26
0
def main():
    parser = OptionParser(
        usage=
        'usage: %prog [options] utxo destaddr1 destaddr2 ..',
        description="For creating multiple utxos from one (for commitments in JM)."
                    "Provide a utxo in form txid:N that has some unspent coins;"
                    "Specify a list of destination addresses and the coins will"
                    "be split equally between them (after bitcoin fees)."

                    "You'll be prompted to enter the private key for the utxo"
                    "during the run; it must be in WIF compressed format."
                    "After the transaction is completed, the utxo strings for"

                    "the new outputs will be shown."
                    "Note that these utxos will not be ready for use as external"

                    "commitments in Joinmarket until 5 confirmations have passed."
                    " BE CAREFUL about handling private keys!"
                    " Don't do this in insecure environments."
                    " Also note this ONLY works for standard (p2pkh) utxos."
    )
    parser.add_option(
        '-v',
        '--validate-utxos',
        action='store_true',
        dest='validate',
        help='validate the utxos and pubkeys provided against the blockchain',
        default=False
    )
    parser.add_option(
        '-o',
        '--validate-only',
        action='store_true',
        dest='vonly',
        help='only validate the provided utxos (file or command line), not add',
        default=False
    )
    (options, args) = parser.parse_args()
    load_program_config()
    if len(args) < 2:
        quit(parser, 'Invalid syntax')
    u = args[0]
    priv = raw_input(
        'input private key for ' + u + ', in WIF compressed format : ')
    u, priv = get_utxo_info(','.join([u, priv]))
    if not u:
        quit(parser, "Failed to parse utxo info: " + u)
    destaddrs = args[1:]
    for d in destaddrs:
        if not validate_address(d):
            quit(parser, "Address was not valid; wrong network?: " + d)
    txsigned = sign(u, priv, destaddrs)
    log.debug("Got signed transaction:\n" + txsigned)
    log.debug("Deserialized:")
    log.debug(pformat(btc.deserialize(txsigned)))
    if raw_input('Would you like to push to the network? (y/n):')[0] != 'y':
        log.debug("You chose not to broadcast the transaction, quitting.")
        return
    jm_single().bc_interface.pushtx(txsigned)
示例#27
0
def setup_blockr(request):
    def blockr_teardown():
        jm_single().config.set("BLOCKCHAIN", "blockchain_source", "regtest")
        jm_single().config.set("BLOCKCHAIN", "network", "testnet")
    request.addfinalizer(blockr_teardown)    
    load_program_config()
    jm_single().config.set("BLOCKCHAIN", "blockchain_source", "blockr")
    jm_single().bc_interface = BlockrInterface(True)
示例#28
0
def setup_blockr(request):
    def blockr_teardown():
        jm_single().config.set("BLOCKCHAIN", "blockchain_source", "regtest")
        jm_single().config.set("BLOCKCHAIN", "network", "testnet")
    request.addfinalizer(blockr_teardown)    
    load_program_config()
    jm_single().config.set("BLOCKCHAIN", "blockchain_source", "blockr")
    jm_single().bc_interface = BlockrInterface(True)
示例#29
0
def test_no_timeout(setup_tx_notify):
    txhex = make_tx_add_notify()
    jm_single().bc_interface.pushtx(txhex)
    time.sleep(6)
    assert unconfirm_called[0]
    assert confirm_called[0]
    assert not timeout_unconfirm_called[0]
    assert not timeout_confirm_called[0]
    return True
示例#30
0
def test_broadcast_not_self(setup_tx_notify):
    cjtx = create_testing_cjtx(['one', 'two', 'three', 'four'])
    jm_single().config.set('POLICY', 'tx_broadcast', 'not-self')
    N = 1000
    for i in xrange(N):
        cjtx.push()
    assert self_pushtx_count[0] == 0
    assert all(a > 1 for a in msgchan_pushtx_count[0].values())
    return True
示例#31
0
def direct_send(wallet, amount, mixdepth, destaddr, answeryes=False):
    """Send coins directly from one mixdepth to one destination address;
    does not need IRC. Sweep as for normal sendpayment (set amount=0).
    """
    #Sanity checks; note destaddr format is carefully checked in startup
    assert isinstance(mixdepth, int)
    assert mixdepth >= 0
    assert isinstance(amount, int)
    assert amount >= 0 and amount < 10000000000
    assert isinstance(wallet, Wallet)

    import bitcoin as btc
    from pprint import pformat
    if amount == 0:
        utxos = wallet.get_utxos_by_mixdepth()[mixdepth]
        if utxos == {}:
            log.error("There are no utxos in mixdepth: " + str(mixdepth) +
                      ", quitting.")
            return
        total_inputs_val = sum([va['value'] for u, va in utxos.iteritems()])
        fee_est = estimate_tx_fee(len(utxos), 1)
        outs = [{"address": destaddr, "value": total_inputs_val - fee_est}]
    else:
        initial_fee_est = estimate_tx_fee(8, 2)  #8 inputs to be conservative
        utxos = wallet.select_utxos(mixdepth, amount + initial_fee_est)
        if len(utxos) < 8:
            fee_est = estimate_tx_fee(len(utxos), 2)
        else:
            fee_est = initial_fee_est
        total_inputs_val = sum([va['value'] for u, va in utxos.iteritems()])
        changeval = total_inputs_val - fee_est - amount
        outs = [{"value": amount, "address": destaddr}]
        change_addr = wallet.get_internal_addr(mixdepth)
        outs.append({"value": changeval, "address": change_addr})

    #Now ready to construct transaction
    log.info("Using a fee of : " + str(fee_est) + " satoshis.")
    if amount != 0:
        log.info("Using a change value of: " + str(changeval) + " satoshis.")
    tx = btc.mktx(utxos.keys(), outs)
    stx = btc.deserialize(tx)
    for index, ins in enumerate(stx['ins']):
        utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index'])
        addr = utxos[utxo]['address']
        tx = btc.sign(tx, index, wallet.get_key_from_addr(addr))
    txsigned = btc.deserialize(tx)
    log.info("Got signed transaction:\n")
    log.info(tx + "\n")
    log.info(pformat(txsigned))
    if not answeryes:
        if raw_input(
                'Would you like to push to the network? (y/n):')[0] != 'y':
            log.info("You chose not to broadcast the transaction, quitting.")
            return
    jm_single().bc_interface.pushtx(tx)
    txid = btc.txhash(tx)
    log.info("Transaction sent: " + txid + ", shutting down")
示例#32
0
def test_broadcast_not_self(setup_tx_notify):
    cjtx = create_testing_cjtx(['one', 'two', 'three', 'four'])
    jm_single().config.set('POLICY', 'tx_broadcast', 'not-self')
    N = 1000
    for i in xrange(N):
        cjtx.push()
    assert self_pushtx_count[0] == 0
    assert all(a > 1 for a in msgchan_pushtx_count[0].values())
    return True
示例#33
0
def test_no_timeout(setup_tx_notify):
    txhex = make_tx_add_notify()
    jm_single().bc_interface.pushtx(txhex)
    time.sleep(6)
    assert unconfirm_called[0]
    assert confirm_called[0]
    assert not timeout_unconfirm_called[0]
    assert not timeout_confirm_called[0]
    return True
示例#34
0
def test_wif_privkeys_invalid(setup_keys):
    #first try to create wif privkey from key of wrong length
    bad_privs = ['\x01\x02' * 17]  #some silly private key but > 33 bytes

    #next try to create wif with correct length but wrong compression byte
    bad_privs.append('\x07' * 32 + '\x02')

    for priv in bad_privs:
        with pytest.raises(Exception) as e_info:
            fake_wif = btc.wif_compressed_privkey(binascii.hexlify(priv))

    #Create a wif with wrong length
    bad_wif1 = btc.bin_to_b58check('\x01\x02' * 34, 128)
    #Create a wif with wrong compression byte
    bad_wif2 = btc.bin_to_b58check('\x07' * 33, 128)
    for bw in [bad_wif1, bad_wif2]:
        with pytest.raises(Exception) as e_info:
            fake_priv = btc.from_wif_privkey(bw)

    #Some invalid b58 from bitcoin repo;
    #none of these are valid as any kind of key or address
    with open("test/base58_keys_invalid.json", "r") as f:
        json_data = f.read()
    invalid_key_list = json.loads(json_data)
    for k in invalid_key_list:
        bad_key = k[0]
        for netval in ["mainnet", "testnet"]:
            jm_single().config.set("BLOCKCHAIN", "network", netval)
            #if using py.test -s ; sanity check to see what's actually being tested
            print 'testing this key: ' + bad_key
            if "decode_privkey" in dir(btc):
                try:
                    bad_key_format = btc.get_privkey_format(bad_key)
                    print 'has correct format: ' + bad_key_format
                except:
                    pass
            #should throw exception
            with pytest.raises(Exception) as e_info:
                if "decode_privkey" in dir(btc):
                    from_wif_key = btc.decode_privkey(bad_key)
                else:
                    from_wif_key = btc.from_wif_compressed_privkey(
                        bad_key, btc.get_version_byte(bad_key))
                #in case the b58 check encoding is valid, we should
                #also check if the leading version byte is in the
                #expected set, and throw an error if not.
                if chr(btc.get_version_byte(bad_key)) not in '\x80\xef':
                    raise Exception("Invalid version byte")
                #the bitcoin library should throw
                #if the compression byte is not there (test not needed
                #for secp256k1 branch since the wif_compressed function checks)
                if "decode_privkey" in dir(btc):
                    if "compressed" in btc.get_privkey_format(bad_key) and \
                   btc.b58check_to_bin(x)[-1] != '\x01':
                        raise Exception("Invalid compression byte")
示例#35
0
def test_wif_privkeys_invalid(setup_keys):
    #first try to create wif privkey from key of wrong length
    bad_privs = ['\x01\x02'*17] #some silly private key but > 33 bytes

    #next try to create wif with correct length but wrong compression byte
    bad_privs.append('\x07'*32 + '\x02')
    
    for priv in bad_privs:
        with pytest.raises(Exception) as e_info:
            fake_wif = btc.wif_compressed_privkey(binascii.hexlify(priv))

    #Create a wif with wrong length
    bad_wif1 = btc.bin_to_b58check('\x01\x02'*34, 128)
    #Create a wif with wrong compression byte
    bad_wif2 = btc.bin_to_b58check('\x07'*33, 128)
    for bw in [bad_wif1, bad_wif2]:
        with pytest.raises(Exception) as e_info:
            fake_priv = btc.from_wif_privkey(bw)

    #Some invalid b58 from bitcoin repo;
    #none of these are valid as any kind of key or address
    with open("test/base58_keys_invalid.json", "r") as f:
        json_data = f.read()
    invalid_key_list = json.loads(json_data)
    for k in invalid_key_list:
        bad_key = k[0]
        for netval in ["mainnet", "testnet"]:
            jm_single().config.set("BLOCKCHAIN", "network", netval)
            #if using py.test -s ; sanity check to see what's actually being tested
            print 'testing this key: ' + bad_key
            if "decode_privkey" in dir(btc):
                try:
                    bad_key_format = btc.get_privkey_format(bad_key)
                    print 'has correct format: ' + bad_key_format
                except:
                    pass
            #should throw exception
            with pytest.raises(Exception) as e_info:
                if "decode_privkey" in dir(btc):
                    from_wif_key = btc.decode_privkey(bad_key)
                else:
                    from_wif_key = btc.from_wif_compressed_privkey(
                        bad_key, btc.get_version_byte(bad_key))
                #in case the b58 check encoding is valid, we should
                #also check if the leading version byte is in the
                #expected set, and throw an error if not.
                if chr(btc.get_version_byte(bad_key)) not in '\x80\xef':
                    raise Exception("Invalid version byte")
                #the bitcoin library should throw
                #if the compression byte is not there (test not needed
                #for secp256k1 branch since the wif_compressed function checks)
                if "decode_privkey" in dir(btc):
                    if "compressed" in btc.get_privkey_format(bad_key) and \
                   btc.b58check_to_bin(x)[-1] != '\x01':
                        raise Exception("Invalid compression byte")
示例#36
0
def test_blockr_estimate_fee(setup_blockr):
    absurd_fee = jm_single().config.getint("POLICY", "absurd_fee_per_kb")
    res = []
    for N in [1, 3, 6]:
        res.append(jm_single().bc_interface.estimate_fee_per_kb(N))
    assert res[0] >= res[2]
    #Note this can fail, it isn't very accurate.
    #assert res[1] >= res[2]
    #sanity checks:
    assert res[0] < absurd_fee
    assert res[2] < absurd_fee
示例#37
0
def test_confirm_timeout(setup_tx_notify):
    txhex = make_tx_add_notify()
    jm_single().bc_interface.tick_forward_chain_interval = -1
    jm_single().bc_interface.pushtx(txhex)
    time.sleep(10)
    jm_single().bc_interface.tick_forward_chain_interval = 2
    assert unconfirm_called[0]
    assert not confirm_called[0]
    assert not timeout_unconfirm_called[0]
    assert timeout_confirm_called[0]
    return True
示例#38
0
def test_confirm_timeout(setup_tx_notify):
    txhex = make_tx_add_notify()
    jm_single().bc_interface.tick_forward_chain_interval = -1
    jm_single().bc_interface.pushtx(txhex)
    time.sleep(10)
    jm_single().bc_interface.tick_forward_chain_interval = 2
    assert unconfirm_called[0]
    assert not confirm_called[0]
    assert not timeout_unconfirm_called[0]
    assert timeout_confirm_called[0]
    return True
示例#39
0
def test_blockr_estimate_fee(setup_blockr):
    absurd_fee = jm_single().config.getint("POLICY", "absurd_fee_per_kb")
    res = []
    for N in [1,3,6]:
        res.append(jm_single().bc_interface.estimate_fee_per_kb(N))
    assert res[0] >= res[2]
    #Note this can fail, it isn't very accurate.
    #assert res[1] >= res[2]
    #sanity checks:
    assert res[0] < absurd_fee
    assert res[2] < absurd_fee
示例#40
0
def do_tx(wallet, amount):
    ins_full = wallet.select_utxos(0, amount)
    cj_addr = wallet.get_internal_addr(1)
    change_addr = wallet.get_internal_addr(0)
    wallet.update_cache_index()
    txid = make_sign_and_push(ins_full, wallet, amount,
                              output_addr=cj_addr,
                              change_addr=change_addr,
                              estimate_fee=True)
    assert txid
    time.sleep(2) #blocks
    jm_single().bc_interface.sync_unspent(wallet)
示例#41
0
def test_absurd_fees(setup_tx_creation):
    """Test triggering of ValueError exception
    if the transaction fees calculated from the blockchain
    interface exceed the limit set in the config.
    """
    jm_single().bc_interface.absurd_fees = True
    #pay into it
    wallet = make_wallets(1, [[2, 0, 0, 0, 1]], 3)[0]['wallet']
    jm_single().bc_interface.sync_wallet(wallet)
    amount = 350000000
    ins_full = wallet.select_utxos(0, amount)
    with pytest.raises(ValueError) as e_info:
        txid = make_sign_and_push(ins_full, wallet, amount, estimate_fee=True)
示例#42
0
 def __init__(self, configdata, nick):
     super(DummyMC, self).__init__(configdata)
     #hacked in here to allow auth without mc-collection
     nick_priv = hashlib.sha256(os.urandom(16)).hexdigest() + '01'
     nick_pubkey = btc.privtopub(nick_priv)
     nick_pkh_raw = hashlib.sha256(nick_pubkey).digest()[:NICK_HASH_LENGTH]
     nick_pkh = btc.changebase(nick_pkh_raw, 256, 58)
     #right pad to maximum possible; b58 is not fixed length.
     #Use 'O' as one of the 4 not included chars in base58.
     nick_pkh += 'O' * (NICK_MAX_ENCODED - len(nick_pkh))
     #The constructed length will be 1 + 1 + NICK_MAX_ENCODED
     nick = JOINMARKET_NICK_HEADER + str(jm_single().JM_VERSION) + nick_pkh
     jm_single().nickname = nick
     self.set_nick(nick, nick_priv, nick_pubkey)
示例#43
0
def do_tx(wallet, amount):
    ins_full = wallet.select_utxos(0, amount)
    cj_addr = wallet.get_internal_addr(1)
    change_addr = wallet.get_internal_addr(0)
    wallet.update_cache_index()
    txid = make_sign_and_push(ins_full,
                              wallet,
                              amount,
                              output_addr=cj_addr,
                              change_addr=change_addr,
                              estimate_fee=True)
    assert txid
    time.sleep(2)  #blocks
    jm_single().bc_interface.sync_unspent(wallet)
示例#44
0
def test_b58_valid_addresses():
    with open("test/base58_keys_valid.json", "r") as f:
        json_data = f.read()
    valid_keys_list = json.loads(json_data)
    for a in valid_keys_list:
        addr, pubkey, prop_dict = a
        if not prop_dict["isPrivkey"]:
            if prop_dict["isTestnet"]:
                jm_single().config.set("BLOCKCHAIN", "network", "testnet")
            else:
                jm_single().config.set("BLOCKCHAIN", "network", "mainnet")
            #if using py.test -s ; sanity check to see what's actually being tested
            print 'testing this address: ' + addr
            res, message = validate_address(addr)
            assert res == True, "Incorrectly failed to validate address: " + addr + " with message: " + message
示例#45
0
    def oid_to_order(self, cjorder, oid, amount):
        total_amount = amount + cjorder.txfee
        mix_balance = self.wallet.get_balance_by_mixdepth()
        filtered_mix_balance = [
            m for m in mix_balance.iteritems() if m[1] >= total_amount
        ]
        if not filtered_mix_balance:
            return None, None, None
        log.debug('mix depths that have enough, filtered_mix_balance = ' +
                  str(filtered_mix_balance))

        # use mix depth that has the closest amount of coins to what this transaction needs
        # keeps coins moving through mix depths more quickly
        # and its more likely to use txos of a similiar size to this transaction
        filtered_mix_balance = sorted(
            filtered_mix_balance,
            key=lambda x: x[1])  #sort smallest to largest usable amount

        log.debug('sorted order of filtered_mix_balance = ' +
                  str(filtered_mix_balance))

        mixdepth = filtered_mix_balance[0][0]

        log.debug('filling offer, mixdepth=' + str(mixdepth))

        # mixdepth is the chosen depth we'll be spending from
        cj_addr = self.wallet.get_internal_addr(
            (mixdepth + 1) % self.wallet.max_mix_depth)
        change_addr = self.wallet.get_internal_addr(mixdepth)

        utxos = self.wallet.select_utxos(mixdepth, total_amount)
        my_total_in = sum([va['value'] for va in utxos.values()])
        real_cjfee = calc_cj_fee(cjorder.ordertype, cjorder.cjfee, amount)
        change_value = my_total_in - amount - cjorder.txfee + real_cjfee
        if change_value <= jm_single().DUST_THRESHOLD:
            log.debug(
                'change value=%d below dust threshold, finding new utxos' %
                (change_value))
            try:
                utxos = self.wallet.select_utxos(
                    mixdepth, total_amount + jm_single().DUST_THRESHOLD)
            except Exception:
                log.debug(
                    'dont have the required UTXOs to make a output above the dust threshold, quitting'
                )
                return None, None, None

        return utxos, cj_addr, change_addr
示例#46
0
def make_sign_and_push(ins_full,
                       wallet,
                       amount,
                       output_addr=None,
                       change_addr=None,
                       hashcode=btc.SIGHASH_ALL):
    total = sum(x['value'] for x in ins_full.values())
    ins = ins_full.keys()
    #random output address and change addr
    output_addr = wallet.get_new_addr(1, 1) if not output_addr else output_addr
    change_addr = wallet.get_new_addr(1, 0) if not change_addr else change_addr
    outs = [{'value': amount,
             'address': output_addr}, {'value': total - amount - 100000,
                                       'address': change_addr}]

    tx = btc.mktx(ins, outs)
    de_tx = btc.deserialize(tx)
    for index, ins in enumerate(de_tx['ins']):
        utxo = ins['outpoint']['hash'] + ':' + str(ins['outpoint']['index'])
        addr = ins_full[utxo]['address']
        priv = wallet.get_key_from_addr(addr)
        if index % 2:
            priv = binascii.unhexlify(priv)
        tx = btc.sign(tx, index, priv, hashcode=hashcode)
    #pushtx returns False on any error
    print btc.deserialize(tx)
    push_succeed = jm_single().bc_interface.pushtx(tx)
    if push_succeed:
        return btc.txhash(tx)
    else:
        return False
示例#47
0
def test_external_commitments(setup_podle):
    """Add this generated commitment to the external list
    {txid:N:{'P':pubkey, 'reveal':{1:{'P2':P2,'s':s,'e':e}, 2:{..},..}}}
    Note we do this *after* the sendpayment test so that the external
    commitments will not erroneously used (they are fake).
    """
    ecs = {}
    tries = jm_single().config.getint("POLICY","taker_utxo_retries")
    for i in range(10):
        priv = os.urandom(32)
        dummy_utxo = btc.sha256(priv)+":2"
        ecs[dummy_utxo] = {}
        ecs[dummy_utxo]['reveal']={}
        for j in range(tries):
            P, P2, s, e, commit = generate_single_podle_sig(priv, j)
            if 'P' not in ecs[dummy_utxo]:
                ecs[dummy_utxo]['P']=P
            ecs[dummy_utxo]['reveal'][j] = {'P2':P2, 's':s, 'e':e}
    btc.add_external_commitments(ecs)
    used, external = btc.get_podle_commitments()
    for  u in external:
        assert external[u]['P'] == ecs[u]['P']
        for i in range(tries):
            for x in ['P2', 's', 'e']:
                assert external[u]['reveal'][str(i)][x] == ecs[u]['reveal'][i][x]
示例#48
0
def add_external_commitments(utxo_datas):
    """Persist the PoDLE commitments for this utxo
    to the commitments.json file. The number of separate
    entries is dependent on the taker_utxo_retries entry, by
    default 3.
    """
    def generate_single_podle_sig(u, priv, i):
        """Make a podle entry for key priv at index i, using a dummy utxo value.
        This calls the underlying 'raw' code based on the class PoDLE, not the
        library 'generate_podle' which intelligently searches and updates commitments.
        """
        #Convert priv to hex
        hexpriv = btc.from_wif_privkey(priv, vbyte=get_p2pk_vbyte())
        podle = btc.PoDLE(u, hexpriv)
        r = podle.generate_podle(i)
        return (r['P'], r['P2'], r['sig'],
                r['e'], r['commit'])
    ecs = {}
    for u, priv in utxo_datas:
        ecs[u] = {}
        ecs[u]['reveal']={}
        for j in range(jm_single().config.getint("POLICY", "taker_utxo_retries")):
            P, P2, s, e, commit = generate_single_podle_sig(u, priv, j)
            if 'P' not in ecs[u]:
                ecs[u]['P']=P
            ecs[u]['reveal'][j] = {'P2':P2, 's':s, 'e':e}
        btc.add_external_commitments(ecs)
示例#49
0
def make_sign_and_push(
    ins_full, wallet, amount, output_addr=None, change_addr=None, hashcode=btc.SIGHASH_ALL, estimate_fee=False
):
    """Utility function for easily building transactions
    from wallets
    """
    total = sum(x["value"] for x in ins_full.values())
    ins = ins_full.keys()
    # random output address and change addr
    output_addr = wallet.get_new_addr(1, 1) if not output_addr else output_addr
    change_addr = wallet.get_new_addr(1, 0) if not change_addr else change_addr
    fee_est = estimate_tx_fee(len(ins), 2) if estimate_fee else 10000
    outs = [{"value": amount, "address": output_addr}, {"value": total - amount - fee_est, "address": change_addr}]

    tx = btc.mktx(ins, outs)
    de_tx = btc.deserialize(tx)
    for index, ins in enumerate(de_tx["ins"]):
        utxo = ins["outpoint"]["hash"] + ":" + str(ins["outpoint"]["index"])
        addr = ins_full[utxo]["address"]
        priv = wallet.get_key_from_addr(addr)
        if index % 2:
            priv = binascii.unhexlify(priv)
        tx = btc.sign(tx, index, priv, hashcode=hashcode)
    # pushtx returns False on any error
    print btc.deserialize(tx)
    push_succeed = jm_single().bc_interface.pushtx(tx)
    if push_succeed:
        return btc.txhash(tx)
    else:
        return False
    def create_my_orders(self):
        mix_balance = self.wallet.get_balance_by_mixdepth()
        if len([b for m, b in mix_balance.iteritems() if b > 0]) == 0:
            log.debug('do not have any coins left')
            return []

        # print mix_balance
        max_mix = max(mix_balance, key=mix_balance.get)
        f = '0'
        if self.ordertype == 'reloffer':
            f = self.cjfee_r
            #minimum size bumped if necessary such that you always profit
            #least 50% of the miner fee
            self.minsize = int(1.5 * self.txfee / float(self.cjfee_r))
        elif ordertype == 'absoffer':
            f = str(self.txfee + self.cjfee_a)
        order = {'oid': 0,
                 'ordertype': self.ordertype,
                 'minsize': self.minsize,
                 'maxsize': mix_balance[max_mix] - max(
                     jm_single().DUST_THRESHOLD,txfee),
                 'txfee': self.txfee,
                 'cjfee': f}

        # sanity check
        assert order['minsize'] >= 0
        assert order['maxsize'] > 0
        assert order['minsize'] <= order['maxsize']

        return [order]
示例#51
0
 def finishcallback(self, coinjointx):
     if coinjointx.all_responded:
         jm_single().bc_interface.add_tx_notify(
                 coinjointx.latest_tx, self.unconfirm_callback,
                 self.confirm_callback, coinjointx.my_cj_addr)
         pushed = coinjointx.self_sign_and_push()
         if pushed:
             self.taker.wallet.remove_old_utxos(coinjointx.latest_tx)
         else:
             log.debug("Failed to push transaction, trying again.")
             self.create_tx()
     else:
         self.ignored_makers += coinjointx.nonrespondants
         log.debug('recreating the tx, ignored_makers=' + str(
                 self.ignored_makers))
         self.create_tx()
示例#52
0
 def pushtx(self):
     push_attempts = 3
     while True:
         ret = self.taker.cjtx.push()
         if ret:
             break
         if push_attempts == 0:
             break
         push_attempts -= 1
         time.sleep(10)
     if ret:
         jm_single().bc_interface.add_tx_notify(
             self.taker.cjtx.latest_tx, self.unconfirm_callback,
             self.confirm_callback, self.taker.cjtx.my_cj_addr,
             self.timeout_callback)
     return ret
示例#53
0
def test_external_commitments(setup_podle):
    """Add this generated commitment to the external list
    {txid:N:{'P':pubkey, 'reveal':{1:{'P2':P2,'s':s,'e':e}, 2:{..},..}}}
    Note we do this *after* the sendpayment test so that the external
    commitments will not erroneously used (they are fake).
    """
    ecs = {}
    tries = jm_single().config.getint("POLICY", "taker_utxo_retries")
    for i in range(10):
        priv = os.urandom(32)
        dummy_utxo = btc.sha256(priv) + ":2"
        ecs[dummy_utxo] = {}
        ecs[dummy_utxo]['reveal'] = {}
        for j in range(tries):
            P, P2, s, e, commit = generate_single_podle_sig(priv, j)
            if 'P' not in ecs[dummy_utxo]:
                ecs[dummy_utxo]['P'] = P
            ecs[dummy_utxo]['reveal'][j] = {'P2': P2, 's': s, 'e': e}
    btc.add_external_commitments(ecs)
    used, external = btc.get_podle_commitments()
    for u in external:
        assert external[u]['P'] == ecs[u]['P']
        for i in range(tries):
            for x in ['P2', 's', 'e']:
                assert external[u]['reveal'][str(
                    i)][x] == ecs[u]['reveal'][i][x]
示例#54
0
    def create_my_orders(self):
        mix_balance = self.wallet.get_balance_by_mixdepth()
        if len([b for m, b in mix_balance.iteritems() if b > 0]) == 0:
            log.debug('do not have any coins left')
            return []

        # print mix_balance
        max_mix = max(mix_balance, key=mix_balance.get)
        f = '0'
        if ordertype == 'relorder':
            f = cjfee_r
        elif ordertype == 'absorder':
            f = str(txfee + cjfee_a)
        order = {'oid': 0,
                 'ordertype': ordertype,
                 'minsize': minsize,
                 'maxsize': mix_balance[max_mix] - jm_single().DUST_THRESHOLD,
                 'txfee': txfee,
                 'cjfee': f}

        # sanity check
        assert order['minsize'] >= 0
        assert order['maxsize'] > 0
        assert order['minsize'] <= order['maxsize']

        return [order]
示例#55
0
    def create_my_orders(self):
        mix_balance = self.wallet.get_balance_by_mixdepth()
        if len([b for m, b in mix_balance.iteritems() if b > 0]) == 0:
            log.debug('do not have any coins left')
            return []

        # print mix_balance
        max_mix = max(mix_balance, key=mix_balance.get)
        f = '0'
        if ordertype == 'reloffer':
            f = cjfee_r
        elif ordertype == 'absoffer':
            f = str(txfee + cjfee_a)
        order = {
            'oid':
            0,
            'ordertype':
            ordertype,
            'minsize':
            minsize,
            'maxsize':
            mix_balance[max_mix] - max(jm_single().DUST_THRESHOLD, txfee),
            'txfee':
            txfee,
            'cjfee':
            f
        }

        # sanity check
        assert order['minsize'] >= 0
        assert order['maxsize'] > 0
        assert order['minsize'] <= order['maxsize']

        return [order]