コード例 #1
0
def main():
    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)
    mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()]
    mcc = MessageChannelCollection(mcs)
    log.info("Starting ob-watcher")
    # todo: is the call to GUITaker needed, or the return. taker unused
    taker = GUITaker(mcc, hostport)
    print('starting irc')

    mcc.run()
コード例 #2
0
def main():
    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)
    mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()]
    mcc = MessageChannelCollection(mcs)
    log.info("Starting ob-watcher")
    # todo: is the call to GUITaker needed, or the return. taker unused
    taker = GUITaker(mcc, hostport)
    print('starting irc')

    mcc.run()
コード例 #3
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()
コード例 #4
0
ファイル: ob-watcher.py プロジェクト: Noughmad/joinmarket
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()
コード例 #5
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)
コード例 #6
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)
コード例 #7
0
ファイル: test_blockr.py プロジェクト: ridiks10/joinmarket
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)
コード例 #8
0
def main():
    load_program_config()
    if isinstance(jm_single().bc_interface,
                  blockchaininterface.BlockrInterface):
        print('You are using the blockr.io website')
        print('You should setup JoinMarket with Bitcoin Core.')
        ret = raw_input('\nContinue Anyways? (y/n):')
        if ret[0] != 'y':
            return
    wallet = Wallet(wallet_file, max_mix_depth=mix_levels)
    jm_single().bc_interface.sync_wallet(wallet)
    jm_single().nickname = nickname
    log.debug('starting yield generator')
    irc = IRCMessageChannel(jm_single().nickname,
                            realname='btcint=' + jm_single().config.get(
                                "BLOCKCHAIN", "blockchain_source"),
                            password=nickserv_password)
    maker = YieldGenerator(irc, wallet)

    def timer_loop(startup=False):  # for oscillator
        if not startup:
            maker.refresh_offers()
        poss_refresh = []
        for x in offer_levels:
            recent_transactions = get_recent_transactions(x['time_frame'])
            if recent_transactions:
                oldest_transaction_time = recent_transactions[-1]['timestamp']
            else:
                oldest_transaction_time = datetime.datetime.now()
            next_refresh = oldest_transaction_time + datetime.timedelta(
                hours=x['time_frame'],
                seconds=1)
            poss_refresh.append(next_refresh)
        next_refresh = sorted(poss_refresh, key=lambda x: x)[0]
        td = next_refresh - datetime.datetime.now()
        seconds_till = (td.days * 24 * 60 * 60) + td.seconds
        log.debug('Next offer refresh for ' + nickname + ' at ' +
                  next_refresh.strftime("%Y-%m-%d %I:%M:%S %p"))
        log.debug('...or after a new transaction shows up.')
        t = threading.Timer(seconds_till, timer_loop)
        t.daemon = True
        t.start()

    timer_loop(startup=True)
    try:
        log.debug('connecting to irc')
        irc.run()
    except:
        log.debug('CRASHING, DUMPING EVERYTHING')
        debug_dump_object(wallet, ['addr_cache', 'keys', 'seed'])
        debug_dump_object(maker)
        debug_dump_object(irc)
        import traceback
        log.debug(traceback.format_exc())
コード例 #9
0
ファイル: test_podle.py プロジェクト: AdamISZ/joinmarket
def setup_podle(request):
    load_program_config()
    prev_commits = False
    #back up any existing commitments
    pcf = btc.get_commitment_file()
    log.debug("Podle file: " + pcf)
    if os.path.exists(pcf):
        os.rename(pcf, pcf + ".bak")
        prev_commits = True
    def teardown():
        if prev_commits:
            os.rename(pcf + ".bak", pcf)
        else:
            os.remove(pcf)
    request.addfinalizer(teardown)
コード例 #10
0
def main():
    load_program_config()
    import sys
    seed = sys.argv[1]
    if isinstance(jm_single().bc_interface,
                  blockchaininterface.BlockrInterface):
        print(
            '\nYou are running a yield generator by polling the blockr.io website')
        print(
            'This is quite bad for privacy. That site is owned by coinbase.com')
        print(
            'Also your bot will run faster and more efficently, you can be immediately notified of new bitcoin network')
        print(
            ' information so your money will be working for you as hard as possible')
        print(
            'Learn how to setup JoinMarket with Bitcoin Core: https://github.com/chris-belcher/joinmarket/wiki/Running-JoinMarket-with-Bitcoin-Core-full-node')
        ret = raw_input('\nContinue? (y/n):')
        if ret[0] != 'y':
            return

    wallet = Wallet(seed, max_mix_depth=mix_levels)
    jm_single().bc_interface.sync_wallet(wallet)

    jm_single().nickname = nickname
    log.debug('starting yield generator')
    irc = IRCMessageChannel(jm_single().nickname,
                            realname='btcint=' + jm_single().config.get(
                                "BLOCKCHAIN", "blockchain_source"),
                            password=nickserv_password)
    maker = YieldGenerator(irc, wallet)
    try:
        log.debug('connecting to irc')
        irc.run()
    except:
        log.debug('CRASHING, DUMPING EVERYTHING')
        debug_dump_object(wallet, ['addr_cache', 'keys', 'seed'])
        debug_dump_object(maker)
        debug_dump_object(irc)
        import traceback
        log.debug(traceback.format_exc())
コード例 #11
0
ファイル: broadcast-tx.py プロジェクト: AdamISZ/joinmarket
def main():
    parser = OptionParser(
        usage=
        'usage: %prog [options] [tx hex]',
        description='Sends a transaction to a random market maker requesting that they broadcast it '
        +
        'to the wider bitcoin network. Used to add a layer between your own IP address and the network '
        +
        'where other methods are not possible.')
    parser.add_option(
        '-w',
        '--wait-time',
        action='store',
        type='float',
        dest='waittime',
        help='wait time in seconds to allow orders to arrive, default=5',
        default=10)
    (options, args) = parser.parse_args()

    if len(args) < 1:
        parser.error('Needs a transaction hex string')
        sys.exit(0)
    txhex = args[0]

    load_program_config()
    jm_single().nickname = random_nick()
    log.debug('starting broadcast-tx')
    mcs = [IRCMessageChannel(c, jm_single().nickname) for c in get_irc_mchannels()]
    mcc = MessageChannelCollection(mcs)
    taker = Broadcaster(mcc, options.waittime, txhex)
    try:
        log.debug('starting message channels')
        mcc.run()
    except:
        log.debug('CRASHING, DUMPING EVERYTHING')
        debug_dump_object(taker)
        import traceback
        log.debug(traceback.format_exc())
コード例 #12
0
def ygmain(ygclass, txfee=1000, cjfee_a=200, cjfee_r=0.002, ordertype='reloffer',
           nickserv_password='', minsize=100000, gaplimit=6):
    import sys

    parser = OptionParser(usage='usage: %prog [options] [wallet file]')
    parser.add_option('-o', '--ordertype', action='store', type='string',
                      dest='ordertype', default=ordertype,
                      help='type of order; can be either reloffer or absoffer')
    parser.add_option('-t', '--txfee', action='store', type='int',
                      dest='txfee', default=txfee,
                      help='minimum miner fee in satoshis')
    parser.add_option('-c', '--cjfee', action='store', type='string',
                      dest='cjfee', default='',
                      help='requested coinjoin fee in satoshis or proportion')
    parser.add_option('-p', '--password', action='store', type='string',
                      dest='password', default=nickserv_password,
                      help='irc nickserv password')
    parser.add_option('-s', '--minsize', action='store', type='int',
                      dest='minsize', default=minsize,
                      help='minimum coinjoin size in satoshis')
    parser.add_option('-g', '--gap-limit', action='store', type="int",
                      dest='gaplimit', default=gaplimit,
                      help='gap limit for wallet, default='+str(gaplimit))
    parser.add_option('--fast',
                      action='store_true',
                      dest='fastsync',
                      default=False,
                      help=('choose to do fast wallet sync, only for Core and '
                      'only for previously synced wallet'))
    (options, args) = parser.parse_args()
    if len(args) < 1:
        parser.error('Needs a wallet')
        sys.exit(0)
    seed = args[0]
    ordertype = options.ordertype
    txfee = options.txfee
    if ordertype == 'reloffer':
        if options.cjfee != '':
            cjfee_r = options.cjfee
        # minimum size is such that you always net profit at least 20%
        #of the miner fee
        minsize = max(int(1.2 * txfee / float(cjfee_r)), options.minsize)
    elif ordertype == 'absoffer':
        if options.cjfee != '':
            cjfee_a = int(options.cjfee)
        minsize = options.minsize
    else:
        parser.error('You specified an incorrect order type which ' +\
                     'can be either reloffer or absoffer')
        sys.exit(0)
    nickserv_password = options.password

    load_program_config()
    if isinstance(jm_single().bc_interface, BlockrInterface):
        c = ('\nYou are running a yield generator by polling the blockr.io '
             'website. This is quite bad for privacy. That site is owned by '
             'coinbase.com Also your bot will run faster and more efficently, '
             'you can be immediately notified of new bitcoin network '
             'information so your money will be working for you as hard as '
             'possibleLearn how to setup JoinMarket with Bitcoin Core: '
             'https://github.com/chris-belcher/joinmarket/wiki/Running'
             '-JoinMarket-with-Bitcoin-Core-full-node')
        print(c)
        ret = raw_input('\nContinue? (y/n):')
        if ret[0] != 'y':
            return

    wallet = Wallet(seed, max_mix_depth=MAX_MIX_DEPTH, gaplimit=gaplimit, extend_mixdepth=True)
    sync_wallet(wallet, fast=options.fastsync)

    mcs = [IRCMessageChannel(c, realname='btcint=' + jm_single().config.get(
                                 "BLOCKCHAIN", "blockchain_source"),
                        password=nickserv_password) for c in get_irc_mchannels()]
    mcc = MessageChannelCollection(mcs)
    log.info('starting yield generator')
    maker = ygclass(mcc, wallet, [options.txfee, cjfee_a, cjfee_r,
                                  options.ordertype, options.minsize])
    try:
        log.info('connecting to message channels')
        mcc.run()
    except:
        log.warn('Quitting! Dumping object contents to logfile.')
        debug_dump_object(wallet, ['addr_cache', 'keys', 'seed'])
        debug_dump_object(maker)
        debug_dump_object(mcc, ['nick_priv', 'nick_pkh_raw'])
        import traceback
        log.debug(traceback.format_exc())
コード例 #13
0
ファイル: sendpayment.py プロジェクト: AdamISZ/joinmarket
def main():
    parser = OptionParser(
        usage=
        'usage: %prog [options] [wallet file / fromaccount] [amount] [destaddr]',
        description='Sends a single payment from a given mixing depth of your '
        +
        'wallet to an given address using coinjoin and then switches off. Also sends from bitcoinqt. '
        +
        'Setting amount to zero will do a sweep, where the entire mix depth is emptied')
    parser.add_option('-f',
        '--txfee',
        action='store',
        type='int',
        dest='txfee',
        default=-1,
        help='number of satoshis per participant to use as the initial estimate '+
        'for the total transaction fee, default=dynamically estimated, note that this is adjusted '+
        'based on the estimated fee calculated after tx construction, based on '+
        'policy set in joinmarket.cfg.')
    parser.add_option(
        '-w',
        '--wait-time',
        action='store',
        type='float',
        dest='waittime',
        help='wait time in seconds to allow orders to arrive, default=15',
        default=15)
    parser.add_option('-N',
                      '--makercount',
                      action='store',
                      type='int',
                      dest='makercount',
                      help='how many makers to coinjoin with, default random from 4 to 6',
                      default=random.randint(4, 6))
    parser.add_option(
        '-C',
        '--choose-cheapest',
        action='store_true',
        dest='choosecheapest',
        default=False,
        help='override weightened offers picking and choose cheapest. this might reduce anonymity.')
    parser.add_option(
        '-P',
        '--pick-orders',
        action='store_true',
        dest='pickorders',
        default=False,
        help=
        'manually pick which orders to take. doesn\'t work while sweeping.')
    parser.add_option('-m',
                      '--mixdepth',
                      action='store',
                      type='int',
                      dest='mixdepth',
                      help='mixing depth to spend from, default=0',
                      default=0)
    parser.add_option('-a',
                          '--amtmixdepths',
                          action='store',
                          type='int',
                          dest='amtmixdepths',
                          help='number of mixdepths in wallet, default 5',
                          default=5)
    parser.add_option('-g',
                      '--gap-limit',
                      type="int",
                      action='store',
                      dest='gaplimit',
                      help='gap limit for wallet, default=6',
                      default=6)
    parser.add_option('--yes',
                      action='store_true',
                      dest='answeryes',
                      default=False,
                      help='answer yes to everything')
    parser.add_option(
        '--rpcwallet',
        action='store_true',
        dest='userpcwallet',
        default=False,
        help=('Use the Bitcoin Core wallet through json rpc, instead '
              'of the internal joinmarket wallet. Requires '
              'blockchain_source=json-rpc'))
    (options, args) = parser.parse_args()

    if len(args) < 3:
        parser.error('Needs a wallet, amount and destination address')
        sys.exit(0)
    wallet_name = args[0]
    amount = int(args[1])
    destaddr = args[2]

    load_program_config()
    addr_valid, errormsg = validate_address(destaddr)
    if not addr_valid:
        print('ERROR: Address invalid. ' + errormsg)
        return

    chooseOrdersFunc = None
    if options.pickorders:
        chooseOrdersFunc = pick_order
        if amount == 0:
            print 'WARNING: You may have to pick offers multiple times'
            print 'WARNING: due to manual offer picking while sweeping'
    elif options.choosecheapest:
        chooseOrdersFunc = cheapest_order_choose
    else:  # choose randomly (weighted)
        chooseOrdersFunc = weighted_order_choose

    # Dynamically estimate a realistic fee if it currently is the default value.
    # At this point we do not know even the number of our own inputs, so
    # we guess conservatively with 2 inputs and 2 outputs each
    if options.txfee == -1:
        options.txfee = max(options.txfee, estimate_tx_fee(2, 2))
        log.debug("Estimated miner/tx fee for each cj participant: "+str(options.txfee))
    assert(options.txfee >= 0)

    log.debug('starting sendpayment')

    if not options.userpcwallet:
        wallet = Wallet(wallet_name, options.amtmixdepths, options.gaplimit)
    else:
        wallet = BitcoinCoreWallet(fromaccount=wallet_name)
    jm_single().bc_interface.sync_wallet(wallet)

    mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()]
    mcc = MessageChannelCollection(mcs)
    taker = SendPayment(mcc, wallet, destaddr, amount, options.makercount,
                        options.txfee, options.waittime, options.mixdepth,
                        options.answeryes, chooseOrdersFunc)
    try:
        log.debug('starting message channels')
        mcc.run()
    except:
        log.debug('CRASHING, DUMPING EVERYTHING')
        debug_dump_object(wallet, ['addr_cache', 'keys', 'wallet_name', 'seed'])
        debug_dump_object(taker)
        import traceback
        log.debug(traceback.format_exc())
コード例 #14
0
# then set maxmixdepth to the length of index_cache
maxmixdepth_configured = True
if not options.maxmixdepth:
    maxmixdepth_configured = False
    options.maxmixdepth = 5

noseed_methods = ["generate", "recover", "listwallets"]
methods = ["display", "displayall", "summary", "showseed", "importprivkey"]
methods.extend(noseed_methods)
noscan_methods = ["showseed", "importprivkey"]

if len(args) < 1:
    parser.error("Needs a wallet file or method")
    sys.exit(0)

load_program_config()

if args[0] in noseed_methods:
    method = args[0]
else:
    seed = args[0]
    method = "display" if len(args) == 1 else args[1].lower()
    wallet = Wallet(
        seed,
        options.maxmixdepth,
        options.gaplimit,
        extend_mixdepth=not maxmixdepth_configured,
        storepassword=(method == "importprivkey"),
    )
    if method not in noscan_methods:
        # if nothing was configured, we override bitcoind's options so that
コード例 #15
0
ファイル: sendpayment.py プロジェクト: zhoudaqing/joinmarket
def main():
    parser = OptionParser(
        usage=
        'usage: %prog [options] [wallet file / fromaccount] [amount] [destaddr]',
        description='Sends a single payment from a given mixing depth of your '
        +
        'wallet to an given address using coinjoin and then switches off. Also sends from bitcoinqt. '
        +
        'Setting amount to zero will do a sweep, where the entire mix depth is emptied'
    )
    parser.add_option(
        '-f',
        '--txfee',
        action='store',
        type='int',
        dest='txfee',
        default=-1,
        help=
        'number of satoshis per participant to use as the initial estimate ' +
        'for the total transaction fee, default=dynamically estimated, note that this is adjusted '
        +
        'based on the estimated fee calculated after tx construction, based on '
        + 'policy set in joinmarket.cfg.')
    parser.add_option(
        '-w',
        '--wait-time',
        action='store',
        type='float',
        dest='waittime',
        help='wait time in seconds to allow orders to arrive, default=15',
        default=15)
    parser.add_option('-N',
                      '--makercount',
                      action='store',
                      type='int',
                      dest='makercount',
                      help='how many makers to coinjoin with, default random '
                      'from 5 to 7; use 0 to send *direct* to a destination '
                      'address, not using Joinmarket',
                      default=random.randint(5, 7))
    parser.add_option(
        '-C',
        '--choose-cheapest',
        action='store_true',
        dest='choosecheapest',
        default=False,
        help=
        'override weightened offers picking and choose cheapest. this might reduce anonymity.'
    )
    parser.add_option(
        '-P',
        '--pick-orders',
        action='store_true',
        dest='pickorders',
        default=False,
        help='manually pick which orders to take. doesn\'t work while sweeping.'
    )
    parser.add_option('-m',
                      '--mixdepth',
                      action='store',
                      type='int',
                      dest='mixdepth',
                      help='mixing depth to spend from, default=0',
                      default=0)
    parser.add_option('-a',
                      '--amtmixdepths',
                      action='store',
                      type='int',
                      dest='amtmixdepths',
                      help='number of mixdepths in wallet, default 5',
                      default=5)
    parser.add_option('-g',
                      '--gap-limit',
                      type="int",
                      action='store',
                      dest='gaplimit',
                      help='gap limit for wallet, default=6',
                      default=6)
    parser.add_option('--yes',
                      action='store_true',
                      dest='answeryes',
                      default=False,
                      help='answer yes to everything')
    parser.add_option(
        '--rpcwallet',
        action='store_true',
        dest='userpcwallet',
        default=False,
        help=('Use the Bitcoin Core wallet through json rpc, instead '
              'of the internal joinmarket wallet. Requires '
              'blockchain_source=json-rpc'))
    parser.add_option('--fast',
                      action='store_true',
                      dest='fastsync',
                      default=False,
                      help=('choose to do fast wallet sync, only for Core and '
                            'only for previously synced wallet'))
    (options, args) = parser.parse_args()

    if len(args) < 3:
        parser.error('Needs a wallet, amount and destination address')
        sys.exit(0)
    wallet_name = args[0]
    amount = int(args[1])
    destaddr = args[2]

    load_program_config()
    addr_valid, errormsg = validate_address(destaddr)
    if not addr_valid:
        print('ERROR: Address invalid. ' + errormsg)
        return

    chooseOrdersFunc = None
    if options.pickorders:
        chooseOrdersFunc = pick_order
        if amount == 0:
            print 'WARNING: You may have to pick offers multiple times'
            print 'WARNING: due to manual offer picking while sweeping'
    elif options.choosecheapest:
        chooseOrdersFunc = cheapest_order_choose
    else:  # choose randomly (weighted)
        chooseOrdersFunc = weighted_order_choose

    # Dynamically estimate a realistic fee if it currently is the default value.
    # At this point we do not know even the number of our own inputs, so
    # we guess conservatively with 2 inputs and 2 outputs each
    if options.txfee == -1:
        options.txfee = max(options.txfee, estimate_tx_fee(2, 2))
        log.info("Estimated miner/tx fee for each cj participant: " +
                 str(options.txfee))
    assert (options.txfee >= 0)

    log.info('starting sendpayment')

    #If we are not direct sending, then minimum_maker setting should
    #not be larger than the requested number of counterparties
    if options.makercount != 0 and options.makercount < jm_single(
    ).config.getint("POLICY", "minimum_makers"):
        log.error("You selected a number of counterparties (" + \
                  str(options.makercount) + \
                  ") less than the "
                  "minimum requirement (" + \
                  str(jm_single().config.getint("POLICY","minimum_makers")) + \
                  "); you can edit the value 'minimum_makers'"
                  " in the POLICY section in joinmarket.cfg to correct this. "
                  "Quitting.")
        exit(0)

    if not options.userpcwallet:
        max_mix_depth = max([options.mixdepth, options.amtmixdepths])
        wallet = Wallet(wallet_name, max_mix_depth, options.gaplimit)
    else:
        wallet = BitcoinCoreWallet(fromaccount=wallet_name)
    sync_wallet(wallet, fast=options.fastsync)

    if options.makercount == 0:
        direct_send(wallet, amount, options.mixdepth, destaddr)
        return

    mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()]
    mcc = MessageChannelCollection(mcs)
    log.info("starting sendpayment")
    taker = SendPayment(mcc, wallet, destaddr, amount, options.makercount,
                        options.txfee, options.waittime, options.mixdepth,
                        options.answeryes, chooseOrdersFunc)
    try:
        log.info('starting message channels')
        mcc.run()
    except:
        log.warn('Quitting! Dumping object contents to logfile.')
        debug_dump_object(wallet,
                          ['addr_cache', 'keys', 'wallet_name', 'seed'])
        debug_dump_object(taker)
        import traceback
        log.debug(traceback.format_exc())
コード例 #16
0
def setup_wallets():
    load_program_config()
コード例 #17
0
ファイル: tumbler.py プロジェクト: AlexCato/joinmarket
def main():
    parser = OptionParser(
            usage='usage: %prog [options] [wallet file] [destaddr(s)...]',
            description=
            'Sends bitcoins to many different addresses using coinjoin in'
            ' an attempt to break the link between them. Sending to multiple '
            ' addresses is highly recommended for privacy. This tumbler can'
            ' be configured to ask for more address mid-run, giving the user'
            ' a chance to click `Generate New Deposit Address` on whatever service'
            ' they are using.')
    parser.add_option(
            '-m',
            '--mixdepthsource',
            type='int',
            dest='mixdepthsrc',
            help=
            'Mixing depth to spend from. Useful if a previous tumbler run prematurely ended with '
            +
            'coins being left in higher mixing levels, this option can be used to resume without needing'
            + ' to send to another address. default=0',
            default=0)
    parser.add_option(
            '-f',
        '--txfee',
        action='store',
        type='int',
        dest='txfee',
        default=-1,
        help='number of satoshis per participant to use as the initial estimate '+
        'for the total transaction fee, default=dynamically estimated, note that this is adjusted '+
        'based on the estimated fee calculated after tx construction, based on '+
        'policy set in joinmarket.cfg.')
    parser.add_option(
            '-a',
            '--addrcount',
            type='int',
            dest='addrcount',
            default=3,
            help=
            'How many destination addresses in total should be used. If not enough are given'
            ' as command line arguments, the script will ask for more. This parameter is required'
            ' to stop amount correlation. default=3')
    parser.add_option(
            '-x',
            '--maxcjfee',
            type='float',
            dest='maxcjfee',
            nargs=2,
            default=(0.01, 10000),
            help='maximum coinjoin fee and bitcoin value the tumbler is '
                 'willing to pay to a single market maker. Both values need to be exceeded, so if '
                 'the fee is 30% but only 500satoshi is paid the tx will go ahead. default=0.01, 10000 (1%, 10000satoshi)')
    parser.add_option(
            '-N',
            '--makercountrange',
            type='float',
            nargs=2,
            action='store',
            dest='makercountrange',
            help=
            'Input the mean and spread of number of makers to use. e.g. 5 1.5 will be a normal distribution '
            'with mean 5 and standard deveation 1.5 inclusive, default=5 1.5',
            default=(5, 1.5))
    parser.add_option(
            '--minmakercount',
            type='int',
            dest='minmakercount',
            default=3,
            help=
            'The minimum maker count in a transaction, random values below this are clamped at this number. default=3')
    parser.add_option(
            '-M',
            '--mixdepthcount',
            type='int',
            dest='mixdepthcount',
            help='How many mixing depths to mix through',
            default=4)
    parser.add_option(
            '-c',
            '--txcountparams',
            type='float',
            nargs=2,
            dest='txcountparams',
            default=(4, 1),
            help=
            'The number of transactions to take coins from one mixing depth to the next, it is'
            ' randomly chosen following a normal distribution. Should be similar to --addrask. '
            'This option controls the parameters of the normal distribution curve. (mean, standard deviation). default=(4, 1)')
    parser.add_option(
            '--mintxcount',
            type='int',
            dest='mintxcount',
            default=1,
            help='The minimum transaction count per mixing level, default=1')
    parser.add_option(
            '--donateamount',
            type='float',
            dest='donateamount',
            default=0,
            help=
            'percent of funds to donate to joinmarket development, or zero to opt out (default=0%)')
    parser.add_option(
            '--amountpower',
            type='float',
            dest='amountpower',
            default=100.0,
            help=
            'The output amounts follow a power law distribution, this is the power, default=100.0')
    parser.add_option(
            '-l',
            '--timelambda',
            type='float',
            dest='timelambda',
            default=30,
            help=
            'Average the number of minutes to wait between transactions. Randomly chosen '
            ' following an exponential distribution, which describes the time between uncorrelated'
            ' events. default=30')
    parser.add_option(
            '-w',
            '--wait-time',
            action='store',
            type='float',
            dest='waittime',
            help='wait time in seconds to allow orders to arrive, default=20',
            default=20)
    parser.add_option(
            '-s',
            '--mincjamount',
            type='int',
            dest='mincjamount',
            default=100000,
            help='minimum coinjoin amount in transaction in satoshi, default 100k')
    parser.add_option(
            '-q',
            '--liquiditywait',
            type='int',
            dest='liquiditywait',
            default=60,
            help=
            'amount of seconds to wait after failing to choose suitable orders before trying again, default 60')
    parser.add_option(
            '--maxbroadcasts',
            type='int',
            dest='maxbroadcasts',
            default=4,
            help=
            'maximum amount of times to broadcast a transaction before giving up and re-creating it, default 4')
    parser.add_option(
            '--maxcreatetx',
            type='int',
            dest='maxcreatetx',
            default=9,
            help=
            'maximum amount of times to re-create a transaction before giving up, default 9')
    (options, args) = parser.parse_args()
    options = vars(options)

    if len(args) < 1:
        parser.error('Needs a wallet file')
        sys.exit(0)
    wallet_file = args[0]
    destaddrs = args[1:]
    print(destaddrs)

    load_program_config()
    for addr in destaddrs:
        addr_valid, errormsg = validate_address(addr)
        if not addr_valid:
            print('ERROR: Address ' + addr + ' invalid. ' + errormsg)
            return

    # Dynamically estimate a realistic fee if it currently is the default value.
    # At this point we do not know even the number of our own inputs, so
    # we guess conservatively with 2 inputs and 2 outputs each
    if options['txfee'] == -1:
        options['txfee'] = max(options['txfee'], estimate_tx_fee(2, 2))
        log.debug("Estimated miner/tx fee for each cj participant: "+str(options['txfee']))
    assert(options['txfee'] >= 0)

    if len(destaddrs) > options['addrcount']:
        options['addrcount'] = len(destaddrs)
    if options['addrcount'] + 1 > options['mixdepthcount']:
        print('not enough mixing depths to pay to all destination addresses, '
              'increasing mixdepthcount')
        options['mixdepthcount'] = options['addrcount'] + 1
    if options['donateamount'] > 10.0:
        # fat finger probably, or misunderstanding
        options['donateamount'] = 0.9

    print(str(options))
    tx_list = generate_tumbler_tx(destaddrs, options)
    if not tx_list:
        return

    tx_list2 = copy.deepcopy(tx_list)
    tx_dict = {}
    for tx in tx_list2:
        srcmixdepth = tx['srcmixdepth']
        tx.pop('srcmixdepth')
        if srcmixdepth not in tx_dict:
            tx_dict[srcmixdepth] = []
        tx_dict[srcmixdepth].append(tx)
    dbg_tx_list = []
    for srcmixdepth, txlist in tx_dict.iteritems():
        dbg_tx_list.append({'srcmixdepth': srcmixdepth, 'tx': txlist})
    log.debug('tumbler transaction list')
    pprint(dbg_tx_list)

    total_wait = sum([tx['wait'] for tx in tx_list])
    print('creates ' + str(len(tx_list)) + ' transactions in total')
    print('waits in total for ' + str(len(tx_list)) + ' blocks and ' + str(
            total_wait) + ' minutes')
    total_block_and_wait = len(tx_list) * 10 + total_wait
    print('estimated time taken ' + str(total_block_and_wait) + ' minutes or ' +
          str(round(total_block_and_wait / 60.0, 2)) + ' hours')
    if options['addrcount'] <= 1:
        print('=' * 50)
        print('WARNING: You are only using one destination address')
        print('this is very bad for privacy')
        print('=' * 50)

    ret = raw_input('tumble with these tx? (y/n):')
    if ret[0] != 'y':
        return

    # NOTE: possibly out of date documentation
    # a couple of modes
    # im-running-from-the-nsa, takes about 80 hours, costs a lot
    # python tumbler.py -a 10 -N 10 5 -c 10 5 -l 50 -M 10 wallet_file 1xxx
    #
    # quick and cheap, takes about 90 minutes
    # python tumbler.py -N 2 1 -c 3 0.001 -l 10 -M 3 -a 1 wallet_file 1xxx
    #
    # default, good enough for most, takes about 5 hours
    # python tumbler.py wallet_file 1xxx
    #
    # for quick testing
    # python tumbler.py -N 2 1 -c 3 0.001 -l 0.1 -M 3 -a 0 wallet_file 1xxx 1yyy
    wallet = Wallet(wallet_file,
                    max_mix_depth=options['mixdepthsrc'] + options['mixdepthcount'])
    jm_single().bc_interface.sync_wallet(wallet)
    jm_single().wait_for_commitments = 1
    mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()]
    mcc = MessageChannelCollection(mcs)
    log.debug('starting tumbler')
    tumbler = Tumbler(mcc, wallet, tx_list, options)
    try:
        log.debug('connecting to message channels')
        mcc.run()
    except:
        log.debug('CRASHING, DUMPING EVERYTHING')
        debug_dump_object(wallet, ['addr_cache', 'keys', 'seed'])
        debug_dump_object(tumbler)
        debug_dump_object(tumbler.cjtx)
        import traceback
        log.debug(traceback.format_exc())
コード例 #18
0
ファイル: sendpayment.py プロジェクト: anonpy/joinmarket
def main():
    parser = OptionParser(
        usage=
        'usage: %prog [options] [wallet file / fromaccount] [amount] [destaddr]',
        description='Sends a single payment from a given mixing depth of your '
        +
        'wallet to an given address using coinjoin and then switches off. Also sends from bitcoinqt. '
        +
        'Setting amount to zero will do a sweep, where the entire mix depth is emptied')
    parser.add_option('-f',
        '--txfee',
        action='store',
        type='int',
        dest='txfee',
        default=5000,
        help='number of satoshis per participant to use as the initial estimate '+
        'for the total transaction fee, default=5000, note that this is adjusted '+
        'based on the estimated fee calculated after tx construction, based on '+
        'policy set in joinmarket.cfg.')
    parser.add_option(
        '-w',
        '--wait-time',
        action='store',
        type='float',
        dest='waittime',
        help='wait time in seconds to allow orders to arrive, default=5',
        default=5)
    parser.add_option('-N',
                      '--makercount',
                      action='store',
                      type='int',
                      dest='makercount',
                      help='how many makers to coinjoin with, default=2',
                      default=2)
    parser.add_option(
        '-C',
        '--choose-cheapest',
        action='store_true',
        dest='choosecheapest',
        default=False,
        help='override weightened offers picking and choose cheapest')
    parser.add_option(
        '-P',
        '--pick-orders',
        action='store_true',
        dest='pickorders',
        default=False,
        help=
        'manually pick which orders to take. doesn\'t work while sweeping.')
    parser.add_option('-m',
                      '--mixdepth',
                      action='store',
                      type='int',
                      dest='mixdepth',
                      help='mixing depth to spend from, default=0',
                      default=0)
    parser.add_option('-g',
                      '--gap-limit',
                      type="int",
                      action='store',
                      dest='gaplimit',
                      help='gap limit for wallet, default=6',
                      default=6)
    parser.add_option('--yes',
                      action='store_true',
                      dest='answeryes',
                      default=False,
                      help='answer yes to everything')
    parser.add_option(
        '--rpcwallet',
        action='store_true',
        dest='userpcwallet',
        default=False,
        help=('Use the Bitcoin Core wallet through json rpc, instead '
              'of the internal joinmarket wallet. Requires '
              'blockchain_source=json-rpc'))
    (options, args) = parser.parse_args()

    if len(args) < 3:
        parser.error('Needs a wallet, amount and destination address')
        sys.exit(0)
    wallet_name = args[0]
    amount = int(args[1])
    destaddr = args[2]

    load_program_config()
    addr_valid, errormsg = validate_address(destaddr)
    if not addr_valid:
        print('ERROR: Address invalid. ' + errormsg)
        return

    chooseOrdersFunc = None
    if options.pickorders:
        chooseOrdersFunc = pick_order
        if amount == 0:
            print 'WARNING: You may have to pick offers multiple times'
            print 'WARNING: due to manual offer picking while sweeping'
    elif options.choosecheapest:
        chooseOrdersFunc = cheapest_order_choose
    else:  # choose randomly (weighted)
        chooseOrdersFunc = weighted_order_choose

    jm_single().nickname = random_nick()

    log.debug('starting sendpayment')

    if not options.userpcwallet:
        wallet = Wallet(wallet_name, options.mixdepth + 1, options.gaplimit)
    else:
        wallet = BitcoinCoreWallet(fromaccount=wallet_name)
    jm_single().bc_interface.sync_wallet(wallet)

    irc = IRCMessageChannel(jm_single().nickname)
    taker = SendPayment(irc, wallet, destaddr, amount, options.makercount,
                        options.txfee, options.waittime, options.mixdepth,
                        options.answeryes, chooseOrdersFunc)
    try:
        log.debug('starting irc')
        irc.run()
    except:
        log.debug('CRASHING, DUMPING EVERYTHING')
        debug_dump_object(wallet, ['addr_cache', 'keys', 'wallet_name', 'seed'])
        debug_dump_object(taker)
        import traceback
        log.debug(traceback.format_exc())
コード例 #19
0
ファイル: add-utxo.py プロジェクト: AdamISZ/joinmarket
def main():
    parser = OptionParser(
        usage=
        'usage: %prog [options] [txid:n]',
        description="Adds one or more utxos to the list that can be used to make "
                    "commitments for anti-snooping. Note that this utxo, and its "
                    "PUBkey, will be revealed to makers, so consider the privacy "
                    "implication. "
                    
                    "It may be useful to those who are having trouble making "
                    "coinjoins due to several unsuccessful attempts (especially "
                    "if your joinmarket wallet is new). "
                    
                    "'Utxo' means unspent transaction output, it must not "
                    "already be spent. "
                    "The options -w, -r and -R offer ways to load these utxos "
                    "from a file or wallet. "
                    "If you enter a single utxo without these options, you will be "
                    "prompted to enter the private key here - it must be in "
                    "WIF compressed format. "

                    "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(
        '-r',
        '--read-from-file',
        action='store',
        type='str',
        dest='in_file',
        help='name of plain text csv file containing utxos, one per line, format: '
        'txid:N, WIF-compressed-privkey'
    )
    parser.add_option(
        '-R',
        '--read-from-json',
        action='store',
        type='str',
        dest='in_json',
        help='name of json formatted file containing utxos with private keys, as '
        'output from "python wallet-tool.py -u -p walletname showutxos"'
        )
    parser.add_option(
        '-w',
        '--load-wallet',
        action='store',
        type='str',
        dest='loadwallet',
        help='name of wallet from which to load utxos and use as commitments.'
        )
    parser.add_option(
        '-g',
        '--gap-limit',
        action='store',
        type='int',
        dest='gaplimit',
        default = 6,
        help='Only to be used with -w; gap limit for Joinmarket wallet, default 6.'
    )
    parser.add_option(
        '-M',
        '--max-mixdepth',
        action='store',
        type='int',
        dest='maxmixdepth',
        default=5,
        help='Only to be used with -w; number of mixdepths for wallet, default 5.'
    )
    parser.add_option(
        '-d',
        '--delete-external',
        action='store_true',
        dest='delete_ext',
        help='deletes the current list of external commitment utxos',
        default=False
        )
    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()
    utxo_data = []
    if options.delete_ext:
        other = options.in_file or options.in_json or options.loadwallet
        if len(args) > 0 or other:
            if raw_input("You have chosen to delete commitments, other arguments "
                         "will be ignored; continue? (y/n)") != 'y':
                print "Quitting"
                sys.exit(0)
        c, e = btc.get_podle_commitments()
        print pformat(e)
        if raw_input(
            "You will remove the above commitments; are you sure? (y/n): ") != 'y':
            print "Quitting"
            sys.exit(0)
        btc.update_commitments(external_to_remove=e)
        print "Commitments deleted."
        sys.exit(0)

    #Three options (-w, -r, -R) for loading utxo and privkey pairs from a wallet,
    #csv file or json file.
    if options.loadwallet:
        os.chdir('..') #yuck (see earlier comment about package)
        wallet = Wallet(options.loadwallet,
                            options.maxmixdepth,
                            options.gaplimit)
        os.chdir(os.path.join(os.getcwd(), 'cmttools'))
        jm_single().bc_interface.sync_wallet(wallet)
        unsp = {}
        for u, av in wallet.unspent.iteritems():
                    addr = av['address']
                    key = wallet.get_key_from_addr(addr)
                    wifkey = btc.wif_compressed_privkey(key, vbyte=get_p2pk_vbyte())
                    unsp[u] = {'address': av['address'],
                               'value': av['value'], 'privkey': wifkey}
        for u, pva  in unsp.iteritems():
            utxo_data.append((u, pva['privkey']))
    elif options.in_file:
        with open(options.in_file, "rb") as f:
            utxo_info = f.readlines()
        for ul in utxo_info:
            ul = ul.rstrip()
            if ul:
                u, priv = get_utxo_info(ul)
                if not u:
                    quit(parser, "Failed to parse utxo info: " + str(ul))
                utxo_data.append((u, priv))
    elif options.in_json:
        if not os.path.isfile(options.in_json):
            print "File: " + options.in_json + " not found."
            sys.exit(0)
        with open(options.in_json, "rb") as f:
            try:
                utxo_json = json.loads(f.read())
            except:
                print "Failed to read json from " + options.in_json
                sys.exit(0)
        for u, pva in utxo_json.iteritems():
            utxo_data.append((u, pva['privkey']))
    elif len(args) == 1:
        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)
        utxo_data.append((u, priv))
    else:
        quit(parser, 'Invalid syntax')
    if options.validate or options.vonly:
        if not validate_utxo_data(utxo_data):
            quit(parser, "Utxos did not validate, quitting")
    if options.vonly:
        sys.exit(0)
    
    #We are adding utxos to the external list
    assert len(utxo_data)
    add_external_commitments(utxo_data)
コード例 #20
0
def setup_tx_notify():
    load_program_config()
    jm_single().config.set('TIMEOUT', 'unconfirm_timeout_sec', '3')
    jm_single().config.set('TIMEOUT', 'confirm_timeout_hours', str(6.0 / 60 / 60))
    jm_single().bc_interface.tick_forward_chain_interval = 2
コード例 #21
0
ファイル: fee-estimation.py プロジェクト: AdamISZ/joinmarket
def main():
    os.chdir(data_dir)
    load_program_config()
    unittest.main()
コード例 #22
0
def setup_tumbler():
    load_program_config()
コード例 #23
0
ファイル: ygrunner.py プロジェクト: zhoudaqing/joinmarket
def setup_ygrunner():
    load_program_config()
コード例 #24
0
def main():
    parser = OptionParser(
            usage=
            'usage: %prog [options] [wallet file] [[dest..] [amount]..]',
            description='Sends a payment from your wallet to an given address'
                        + ' using coinjoin but for users who dont mind '
                        + 'waiting. First acts as a maker, announcing an order'
                        + ' and waiting for someone to fill it. After a set '
                        + 'period of time, gives up waiting and acts as a taker'
                        + ' and coinjoins any remaining coins. Is able to send'
                        + ' to multiple locations one after another. [dest] '
                        + 'can be multiple addresses or a xpub BIP32 key. xpub'
                        + ' keys can be optionally followed with :index to '
                        + 'start from another address than zero')
    parser.add_option(
            '-f',
            '--txfee',
            action='store',
            type='int',
            dest='txfee',
            default=1000,
            help='miner fee contribution, in satoshis, default=1000')
    parser.add_option(
            '-N',
            '--makercount',
            action='store',
            type='int',
            dest='makercount',
            help='how many makers to coinjoin with, default random '
                 'from 5 to 7',
            default=random.randint(5, 7))
    parser.add_option(
            '-w',
            '--wait-time',
            action='store',
            type='float',
            dest='waittime',
            help='wait time in hours as a maker before becoming a taker, ' +
                'or zero to wait forever, default=8',
            default=8)
    parser.add_option(
            '-c',
            '--base-cjfee',
            action='store',
            type='int',
            dest='cjfee_base',
            help=
            'base coinjoin fee asked for when being a maker, in satoshis per' +
                ' order filled, default=500',
            default=500)
    parser.add_option(
            '-a',
            '--add-cjfee',
            action='store',
            type='int',
            dest='cjfee_add',
            help=
            'additional coinjoin fee asked for when being a maker when '
                + 'coinjoin amount not exact, in satoshis per order filled'
                + ', default=1000',
            default=1000)
    parser.add_option(
            '-m',
            '--mixdepth',
            action='store',
            type='int',
            dest='mixdepth',
            help='mixing depth to spend from, default=0',
            default=0)
    parser.add_option(
            '--rpcwallet',
            action='store_true',
            dest='userpcwallet',
            default=False,
            help=
            'Use the Bitcoin Core wallet through json rpc, instead of the '
            + 'internal joinmarket wallet. Requires blockchain_source=json-rpc.'
            + ' NOT IMPLEMENTED YET')
    parser.add_option('--fast',
                      action='store_true',
                      dest='fastsync',
                      default=False,
                      help=('choose to do fast wallet sync, only for Core and '
                      'only for previously synced wallet'))
    parser.add_option(
            '-x',
            '--maxcjfee',
            type='float',
            dest='maxcjfee',
            nargs=2,
            default=(0.01, 10000),
            help='maximum coinjoin fee and bitcoin value the taker is ' +
                 'willing to pay to a single market maker. Both values need' +
                 ' to be exceeded, so if the fee is 30% but only 500satoshi ' +
                 'is paid the tx will go ahead. default=0.01, 10000 ' +
                 '(1%, 10000satoshi)')
    parser.add_option(
            '-q',
            '--liquiditywait',
            type='int',
            dest='liquiditywait',
            default=20,
            help=
            'amount of seconds to wait after failing to choose suitable orders'
            ' before trying again, default 20')
    parser.add_option(
            '-u',
            '--minoutputsize',
            type='int',
            dest='minoutputsize',
            nargs=1,
            default=30000,
            help='minimum size of output in satoshis produced by '
                'patientsendpayment. default=30000 satoshi')
    
    (options, args) = parser.parse_args()

    if len(args) < 3:
        parser.error('Needs a wallet, amount and destination address')
        sys.exit(0)
    wallet_name = args[0]

    load_program_config()

    send_jobs = []
    destination = None
    for ar in args[1:]:
        if ar.isdigit():
            if destination == None:
                log.error('found amount without destination')
                return
            elif isinstance(destination, list):
                send_jobs.append( {'amount': int(ar), 'addresses': 
                    destination, 'index': 0} )
            elif isinstance(destination, tuple):
                send_jobs.append( {'amount': int(ar), 'xpub': destination[0]
                , 'index': destination[1]} )
            else:
                assert False
            destination = None
        else:
            if validate_address(ar)[0]:
                if destination == None:
                    destination = []
                destination.append(ar)
            else:
                index = 0
                colon = ar.find(':')
                if colon > -1:
                    index = int(ar[colon+1:])
                    ar = ar[:colon]
                if is_bip32_pubkey(ar):
                    destination = (ar, index)
                else:
                    log.error('unable to parse destination: ' + ar)
                    return
    if destination != None:
        log.error('missing amount')
        return

    for j in send_jobs:
        print('sending ' + str(j['amount']) + ' satoshi to: ')
        if 'addresses' in j:
            for a in j['addresses']:
                print('  ' + get_next_address(j))
        else:
            print('  ' + j['xpub'] + '\n  starting from index: ' + 
                str(j['index']) + '. first 5 addresses:')
            index_cache = j['index']
            for i in range(5):
                print('    ' + get_next_address(j))
            j['index'] = index_cache

    waittime = timedelta(hours=options.waittime).total_seconds()

    # todo: this section doesn't make a lot of sense
    if not options.userpcwallet:
        wallet = Wallet(wallet_name, options.mixdepth + 1)
    else:
        print 'not implemented yet'
        sys.exit(0)
    # wallet = BitcoinCoreWallet(fromaccount=wallet_name)
    sync_wallet(wallet, fast=options.fastsync)

    available_balance = wallet.get_balance_by_mixdepth()[options.mixdepth]
    total_amount = sum((j['amount'] for j in send_jobs))
    if available_balance < total_amount:
        print 'not enough money at mixdepth=%d, exiting' % options.mixdepth
        return

    log.info('Running patient sender of a payment')
    mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()]
    mcc = MessageChannelCollection(mcs)
    PatientSendPayment(mcc, wallet, send_jobs, options, waittime)
    try:
        mcc.run()
    except:
        log.warn('CRASHING, DUMPING EVERYTHING')
        debug_dump_object(wallet, ['addr_cache', 'keys', 'seed'])
        # todo: looks wrong.  dump on the class object?
        # debug_dump_object(taker)
        import traceback
        traceback.print_exc()
コード例 #25
0
ファイル: test_tumbler.py プロジェクト: dan-da/joinmarket
def setup_tumbler():
    load_program_config()
コード例 #26
0
def setup_messaging():
    #Trigger PING LAG sending artificially
    joinmarket.irc.PING_INTERVAL = 3
    load_program_config()
コード例 #27
0
def setup_regtest():
    load_program_config()
コード例 #28
0
def setup_tx_notify():
    load_program_config()
コード例 #29
0
ファイル: ygrunner.py プロジェクト: JoinMarket-Org/joinmarket
def setup_ygrunner():
    load_program_config()
    
コード例 #30
0
def main():
    parser = OptionParser(
            usage=
            'usage: %prog [options] [wallet file / fromaccount] [amount] [destaddr]',
            description='Sends a payment from your wallet to an given address' +
                        ' using coinjoin. First acts as a maker, announcing an order and ' +
                        'waiting for someone to fill it. After a set period of time, gives' +
                        ' up waiting and acts as a taker and coinjoins any remaining coins')
    parser.add_option(
            '-f',
            '--txfee',
            action='store',
            type='int',
            dest='txfee',
            default=10000,
            help='miner fee contribution, in satoshis, default=10000')
    parser.add_option(
            '-N',
            '--makercount',
            action='store',
            type='int',
            dest='makercount',
            help=
            'how many makers to coinjoin with when taking liquidity, default=2',
            default=2)
    parser.add_option(
            '-w',
            '--wait-time',
            action='store',
            type='float',
            dest='waittime',
            help='wait time in hours as a maker before becoming a taker, default=8',
            default=8)
    parser.add_option(
            '-c',
            '--cjfee',
            action='store',
            type='int',
            dest='cjfee',
            help=
            'coinjoin fee asked for when being a maker, in satoshis per order filled, default=50000',
            default=50000)
    parser.add_option(
            '-m',
            '--mixdepth',
            action='store',
            type='int',
            dest='mixdepth',
            help='mixing depth to spend from, default=0',
            default=0)
    parser.add_option(
            '--rpcwallet',
            action='store_true',
            dest='userpcwallet',
            default=False,
            help=
            'Use the Bitcoin Core wallet through json rpc, instead of the internal joinmarket '
            + 'wallet. Requires blockchain_source=json-rpc')
    (options, args) = parser.parse_args()

    if len(args) < 3:
        parser.error('Needs a wallet, amount and destination address')
        sys.exit(0)
    wallet_name = args[0]
    amount = int(args[1])
    destaddr = args[2]

    load_program_config()
    addr_valid, errormsg = validate_address(destaddr)
    if not addr_valid:
        print 'ERROR: Address invalid. ' + errormsg
        return

    waittime = timedelta(hours=options.waittime).total_seconds()
    print 'txfee=%d cjfee=%d waittime=%s makercount=%d' % (
        options.txfee, options.cjfee, str(timedelta(hours=options.waittime)),
        options.makercount)

    # todo: this section doesn't make a lot of sense
    if not options.userpcwallet:
        wallet = Wallet(wallet_name, options.mixdepth + 1)
    else:
        print 'not implemented yet'
        sys.exit(0)
    # wallet = BitcoinCoreWallet(fromaccount=wallet_name)
    jm_single().bc_interface.sync_wallet(wallet)

    available_balance = wallet.get_balance_by_mixdepth()[options.mixdepth]
    if available_balance < amount:
        print 'not enough money at mixdepth=%d, exiting' % options.mixdepth
        return

    jm_single().nickname = random_nick()

    log.debug('Running patient sender of a payment')

    irc = IRCMessageChannel(jm_single().nickname)
    PatientSendPayment(irc, wallet, destaddr, amount, options.makercount,
                             options.txfee, options.cjfee, waittime,
                             options.mixdepth)
    try:
        irc.run()
    except:
        log.debug('CRASHING, DUMPING EVERYTHING')
        debug_dump_object(wallet, ['addr_cache', 'keys', 'seed'])
        # todo: looks wrong.  dump on the class object?
        # debug_dump_object(taker)
        import traceback
        traceback.print_exc()
コード例 #31
0
def main():
    global txfee, cjfee_a, cjfee_r, ordertype, nickserv_password, minsize, mix_levels
    import sys

    parser = OptionParser(usage='usage: %prog [options] [wallet file]')
    parser.add_option('-o',
                      '--ordertype',
                      action='store',
                      type='string',
                      dest='ordertype',
                      default=ordertype,
                      help='type of order; can be either relorder or absorder')
    parser.add_option('-t',
                      '--txfee',
                      action='store',
                      type='int',
                      dest='txfee',
                      default=txfee,
                      help='minimum miner fee in satoshis')
    parser.add_option('-c',
                      '--cjfee',
                      action='store',
                      type='string',
                      dest='cjfee',
                      default='',
                      help='requested coinjoin fee in satoshis or proportion')
    parser.add_option('-n',
                      '--nickname',
                      action='store',
                      type='string',
                      dest='nickname',
                      default=jm_single().nickname,
                      help='irc nickname')
    parser.add_option('-p',
                      '--password',
                      action='store',
                      type='string',
                      dest='password',
                      default=nickserv_password,
                      help='irc nickserv password')
    parser.add_option('-s',
                      '--minsize',
                      action='store',
                      type='int',
                      dest='minsize',
                      default=minsize,
                      help='minimum coinjoin size in satoshis')
    parser.add_option('-m',
                      '--mixlevels',
                      action='store',
                      type='int',
                      dest='mixlevels',
                      default=mix_levels,
                      help='number of mixdepths to use')
    (options, args) = parser.parse_args()
    if len(args) < 1:
        parser.error('Needs a wallet')
        sys.exit(0)
    seed = args[0]
    ordertype = options.ordertype
    txfee = options.txfee
    if ordertype == 'relorder':
        if options.cjfee != '':
            cjfee_r = options.cjfee
        # minimum size is such that you always net profit at least 20% of the miner fee
        minsize = max(int(1.2 * txfee / float(cjfee_r)), options.minsize)
    elif ordertype == 'absorder':
        if options.cjfee != '':
            cjfee_a = int(options.cjfee)
        minsize = options.minsize
    else:
        parser.error(
            'You specified an incorrect order type which can be either relorder or absorder'
        )
        sys.exit(0)
    if jm_single().nickname == options.nickname:
        jm_single().nickname = random_nick()
    else:
        jm_single().nickname = options.nickname
    nickserv_password = options.password
    mix_levels = options.mixlevels

    load_program_config()
    if isinstance(jm_single().bc_interface, BlockrInterface):
        c = ('\nYou are running a yield generator by polling the blockr.io '
             'website. This is quite bad for privacy. That site is owned by '
             'coinbase.com Also your bot will run faster and more efficently, '
             'you can be immediately notified of new bitcoin network '
             'information so your money will be working for you as hard as '
             'possibleLearn how to setup JoinMarket with Bitcoin Core: '
             'https://github.com/chris-belcher/joinmarket/wiki/Running'
             '-JoinMarket-with-Bitcoin-Core-full-node')
        print(c)
        ret = raw_input('\nContinue? (y/n):')
        if ret[0] != 'y':
            return

    wallet = Wallet(seed, max_mix_depth=mix_levels)
    jm_single().bc_interface.sync_wallet(wallet)

    # nickname is set way above
    # nickname

    log.debug('starting yield generator')
    irc = IRCMessageChannel(
        jm_single().nickname,
        realname='btcint=' +
        jm_single().config.get("BLOCKCHAIN", "blockchain_source"),
        password=nickserv_password)
    maker = YieldGenerator(irc, wallet)
    try:
        log.debug('connecting to irc')
        irc.run()
    except:
        log.debug('CRASHING, DUMPING EVERYTHING')
        debug_dump_object(wallet, ['addr_cache', 'keys', 'seed'])
        debug_dump_object(maker)
        debug_dump_object(irc)
        import traceback
        log.debug(traceback.format_exc())
コード例 #32
0
def main():
    parser = OptionParser(
        usage=
        'usage: %prog [options] [cjamount] [cjaddr] [changeaddr] [utxos..]',
        description=('Creates an unsigned coinjoin transaction. Outputs '
                     'a partially signed transaction hex string. The user '
                     'must sign their inputs independently and broadcast '
                     'them. The JoinMarket protocol requires the taker to '
                     'have a single p2pk UTXO input to use to '
                     'authenticate the  encrypted messages. For this '
                     'reason you must pass auth utxo and the '
                     'corresponding private key'))

    # for cjamount=0 do a sweep, and ignore change address
    parser.add_option('-f',
                      '--txfee',
                      action='store',
                      type='int',
                      dest='txfee',
                      default=10000,
                      help='total miner fee in satoshis, default=10000')
    parser.add_option(
        '-w',
        '--wait-time',
        action='store',
        type='float',
        dest='waittime',
        help='wait time in seconds to allow orders to arrive, default=5',
        default=5)
    parser.add_option('-N',
                      '--makercount',
                      action='store',
                      type='int',
                      dest='makercount',
                      help='how many makers to coinjoin with, default=2',
                      default=2)
    parser.add_option(
        '-C',
        '--choose-cheapest',
        action='store_true',
        dest='choosecheapest',
        default=False,
        help='override weightened offers picking and choose cheapest')
    parser.add_option(
        '-P',
        '--pick-orders',
        action='store_true',
        dest='pickorders',
        default=False,
        help='manually pick which orders to take. doesn\'t work while sweeping.'
    )
    parser.add_option('--yes',
                      action='store_true',
                      dest='answeryes',
                      default=False,
                      help='answer yes to everything')
    # TODO implement parser.add_option('-n', '--no-network',
    # action='store_true', dest='nonetwork', default=False, help='dont query
    # the blockchain interface, instead user must supply value of UTXOs on '
    # + ' command line in the format txid:output/value-in-satoshi')
    (options, args) = parser.parse_args()

    if len(args) < 4:
        parser.error(
            'Needs an amount, destination address, change address and utxos ')
        sys.exit(0)
    cjamount = int(args[0])
    destaddr = args[1]
    changeaddr = args[2]
    cold_utxos = args[3:]

    load_program_config()
    addr_valid1, errormsg1 = validate_address(destaddr)
    errormsg2 = None
    # if amount = 0 dont bother checking changeaddr so user can write any junk
    if cjamount != 0:
        addr_valid2, errormsg2 = validate_address(changeaddr)
    else:
        addr_valid2 = True
    if not addr_valid1 or not addr_valid2:
        if not addr_valid1:
            print 'ERROR: Address invalid. ' + errormsg1
        else:
            print 'ERROR: Address invalid. ' + errormsg2
        return

    query_result = jm_single().bc_interface.query_utxo_set(cold_utxos)
    if None in query_result:
        print query_result
    utxo_data = {}
    for utxo, data in zip(cold_utxos, query_result):
        utxo_data[utxo] = {'address': data['address'], 'value': data['value']}
    print("Got this utxo data: " + str(utxo_data))
    if options.pickorders and cjamount != 0:  # cant use for sweeping
        chooseOrdersFunc = pick_order
    elif options.choosecheapest:
        chooseOrdersFunc = cheapest_order_choose
    else:  # choose randomly (weighted)
        chooseOrdersFunc = weighted_order_choose

    wallet = AbstractWallet()
    mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()]
    mcc = MessageChannelCollection(mcs)
    taker = CreateUnsignedTx(mcc, wallet, cjamount, destaddr, changeaddr,
                             utxo_data, options, chooseOrdersFunc)
    log.debug('starting create-unsigned-tx')
    try:
        log.info('starting message channels')
        mcc.run()
    except:
        log.warn('CRASHING, DUMPING EVERYTHING')
        debug_dump_object(wallet,
                          ['addr_cache', 'keys', 'wallet_name', 'seed'])
        debug_dump_object(taker)
        import traceback
        log.debug(traceback.format_exc())
コード例 #33
0
ファイル: test_donations.py プロジェクト: AdamISZ/joinmarket
def setup_donations():
    load_program_config()
コード例 #34
0
def main():
    parser = OptionParser(
            usage='usage: %prog [options] [auth utxo] [cjamount] [cjaddr] ['
                  'changeaddr] [utxos..]',
            description=('Creates an unsigned coinjoin transaction. Outputs '
                         'a partially signed transaction hex string. The user '
                         'must sign their inputs independently and broadcast '
                         'them. The JoinMarket protocol requires the taker to '
                         'have a single p2pk UTXO input to use to '
                         'authenticate the  encrypted messages. For this '
                         'reason you must pass auth utxo and the '
                         'corresponding private key'))

    # for cjamount=0 do a sweep, and ignore change address
    parser.add_option(
            '-f',
            '--txfee',
            action='store',
            type='int',
            dest='txfee',
            default=10000,
            help='total miner fee in satoshis, default=10000')
    parser.add_option(
            '-w',
            '--wait-time',
            action='store',
            type='float',
            dest='waittime',
            help='wait time in seconds to allow orders to arrive, default=5',
            default=5)
    parser.add_option(
            '-N',
            '--makercount',
            action='store',
            type='int',
            dest='makercount',
            help='how many makers to coinjoin with, default=2',
            default=2)
    parser.add_option(
            '-C',
            '--choose-cheapest',
            action='store_true',
            dest='choosecheapest',
            default=False,
            help='override weightened offers picking and choose cheapest')
    parser.add_option(
            '-P',
            '--pick-orders',
            action='store_true',
            dest='pickorders',
            default=False,
            help=
            'manually pick which orders to take. doesn\'t work while sweeping.')
    parser.add_option(
            '--yes',
            action='store_true',
            dest='answeryes',
            default=False,
            help='answer yes to everything')
    # TODO implement parser.add_option('-n', '--no-network',
    # action='store_true', dest='nonetwork', default=False, help='dont query
    # the blockchain interface, instead user must supply value of UTXOs on '
    # + ' command line in the format txid:output/value-in-satoshi')
    (options, args) = parser.parse_args()

    if len(args) < 3:
        parser.error('Needs a wallet, amount and destination address')
        sys.exit(0)
    auth_utxo = args[0]
    cjamount = int(args[1])
    destaddr = args[2]
    changeaddr = args[3]
    cold_utxos = args[4:]

    load_program_config()
    addr_valid1, errormsg1 = validate_address(destaddr)
    errormsg2 = None
    # if amount = 0 dont bother checking changeaddr so user can write any junk
    if cjamount != 0:
        addr_valid2, errormsg2 = validate_address(changeaddr)
    else:
        addr_valid2 = True
    if not addr_valid1 or not addr_valid2:
        if not addr_valid1:
            print 'ERROR: Address invalid. ' + errormsg1
        else:
            print 'ERROR: Address invalid. ' + errormsg2
        return

    all_utxos = [auth_utxo] + cold_utxos
    query_result = jm_single().bc_interface.query_utxo_set(all_utxos)
    if None in query_result:
        print query_result
    utxo_data = {}
    for utxo, data in zip(all_utxos, query_result):
        utxo_data[utxo] = {'address': data['address'], 'value': data['value']}
    auth_privkey = raw_input('input private key for ' + utxo_data[auth_utxo][
        'address'] + ' :')
    if utxo_data[auth_utxo]['address'] != btc.privtoaddr(
            auth_privkey, get_p2pk_vbyte()):
        print 'ERROR: privkey does not match auth utxo'
        return

    if options.pickorders and cjamount != 0:  # cant use for sweeping
        chooseOrdersFunc = pick_order
    elif options.choosecheapest:
        chooseOrdersFunc = cheapest_order_choose
    else:  # choose randomly (weighted)
        chooseOrdersFunc = weighted_order_choose

    jm_single().nickname = random_nick()
    log.debug('starting sendpayment')

    class UnsignedTXWallet(AbstractWallet):

        def get_key_from_addr(self, addr):
            log.debug('getting privkey of ' + addr)
            if btc.privtoaddr(auth_privkey, get_p2pk_vbyte()) != addr:
                raise RuntimeError('privkey doesnt match given address')
            return auth_privkey

    wallet = UnsignedTXWallet()
    irc = IRCMessageChannel(jm_single().nickname)
    taker = CreateUnsignedTx(irc, wallet, auth_utxo, cjamount, destaddr,
                             changeaddr, utxo_data, options, chooseOrdersFunc)
    try:
        log.debug('starting irc')
        irc.run()
    except:
        log.debug('CRASHING, DUMPING EVERYTHING')
        debug_dump_object(wallet, ['addr_cache', 'keys', 'wallet_name', 'seed'])
        debug_dump_object(taker)
        import traceback
        log.debug(traceback.format_exc())
コード例 #35
0
def setup_tx_creation():
    load_program_config()
コード例 #36
0
def setup_messaging():
    #Trigger PING LAG sending artificially
    joinmarket.irc.PING_INTERVAL = 3    
    load_program_config()
コード例 #37
0
def setup_tx_notify():
    load_program_config()
    jm_single().bc_interface = DummyBlockchainInterface()
    jm_single().maker_timeout_sec = 1
コード例 #38
0
def main():
    global txfee, cjfee_a, cjfee_r, ordertype, nickserv_password, minsize, mix_levels
    import sys

    parser = OptionParser(usage='usage: %prog [options] [wallet file]')
    parser.add_option('-o', '--ordertype', action='store', type='string', dest='ordertype', default=ordertype,
                      help='type of order; can be either relorder or absorder')
    parser.add_option('-t', '--txfee', action='store', type='int', dest='txfee', default=txfee,
                      help='minimum miner fee in satoshis')
    parser.add_option('-c', '--cjfee', action='store', type='string', dest='cjfee', default='',
                      help='requested coinjoin fee in satoshis or proportion')
    parser.add_option('-n', '--nickname', action='store', type='string', dest='nickname', default=jm_single().nickname,
                      help='irc nickname')
    parser.add_option('-p', '--password', action='store', type='string', dest='password', default=nickserv_password,
                      help='irc nickserv password')
    parser.add_option('-s', '--minsize', action='store', type='int', dest='minsize', default=minsize,
                      help='minimum coinjoin size in satoshis')
    parser.add_option('-m', '--mixlevels', action='store', type='int', dest='mixlevels', default=mix_levels,
                      help='number of mixdepths to use')
    (options, args) = parser.parse_args()
    if len(args) < 1:
        parser.error('Needs a wallet')
        sys.exit(0)
    seed = args[0]
    ordertype = options.ordertype
    txfee = options.txfee
    if ordertype == 'relorder':
        if options.cjfee != '':
            cjfee_r = options.cjfee
        # minimum size is such that you always net profit at least 20% of the miner fee
        minsize = max(int(1.2 * txfee / float(cjfee_r)), options.minsize)
    elif ordertype == 'absorder':
        if options.cjfee != '':
            cjfee_a = int(options.cjfee)
        minsize = options.minsize
    else:
        parser.error('You specified an incorrect order type which can be either relorder or absorder')
        sys.exit(0)
    if jm_single().nickname == options.nickname:
        jm_single().nickname = random_nick()
    else:
        jm_single().nickname = options.nickname
    nickserv_password = options.password
    mix_levels = options.mixlevels

    load_program_config()
    if isinstance(jm_single().bc_interface, BlockrInterface):
        c = ('\nYou are running a yield generator by polling the blockr.io '
             'website. This is quite bad for privacy. That site is owned by '
             'coinbase.com Also your bot will run faster and more efficently, '
             'you can be immediately notified of new bitcoin network '
             'information so your money will be working for you as hard as '
             'possibleLearn how to setup JoinMarket with Bitcoin Core: '
             'https://github.com/chris-belcher/joinmarket/wiki/Running'
             '-JoinMarket-with-Bitcoin-Core-full-node')
        print(c)
        ret = raw_input('\nContinue? (y/n):')
        if ret[0] != 'y':
            return

    wallet = Wallet(seed, max_mix_depth=mix_levels)
    jm_single().bc_interface.sync_wallet(wallet)

    # nickname is set way above
    # nickname

    log.debug('starting yield generator')
    irc = IRCMessageChannel(jm_single().nickname,
                            realname='btcint=' + jm_single().config.get(
                                "BLOCKCHAIN", "blockchain_source"),
                            password=nickserv_password)
    maker = YieldGenerator(irc, wallet)
    try:
        log.debug('connecting to irc')
        irc.run()
    except:
        log.debug('CRASHING, DUMPING EVERYTHING')
        debug_dump_object(wallet, ['addr_cache', 'keys', 'seed'])
        debug_dump_object(maker)
        debug_dump_object(irc)
        import traceback
        log.debug(traceback.format_exc())