def generate_tumbler_tx(destaddrs, options):
    # sends the coins up through a few mixing depths
    # send to the destination addresses from different mixing depths

    # simple algo, move coins completely from one mixing depth to the next
    # until you get to the end, then send to destaddrs

    # txcounts for going completely from one mixdepth to the next
    # follows a normal distribution
    txcounts = rand_norm_array(options.txcountparams[0],
                               options.txcountparams[1], options.mixdepthcount)
    txcounts = lower_bounded_int(txcounts, options.mintxcount)
    tx_list = []
    for m, txcount in enumerate(txcounts):
        # assume that the sizes of outputs will follow a power law
        amount_fractions = rand_pow_array(options.amountpower, txcount)
        amount_fractions = [1.0 - x for x in amount_fractions]
        amount_fractions = [x / sum(amount_fractions) for x in amount_fractions]
        # transaction times are uncorrelated
        # time between events in a poisson process followed exp
        waits = rand_exp_array(options.timelambda, txcount)
        # number of makers to use follows a normal distribution
        makercounts = rand_norm_array(options.makercountrange[0],
                                      options.makercountrange[1], txcount)
        makercounts = lower_bounded_int(makercounts, options.minmakercount)
        if m == options.mixdepthcount - options.addrcount and options.donateamount:
            tx_list.append({'amount_fraction': 0,
                            'wait': round(waits[0], 2),
                            'srcmixdepth': m + options.mixdepthsrc,
                            'makercount': makercounts[0],
                            'destination': 'internal'})
        for amount_fraction, wait, makercount in zip(amount_fractions, waits,
                                                     makercounts):
            tx = {'amount_fraction': amount_fraction,
                  'wait': round(wait, 2),
                  'srcmixdepth': m + options.mixdepthsrc,
                  'makercount': makercount,
                  'destination': 'internal'}
            tx_list.append(tx)

    addrask = options.addrcount - len(destaddrs)
    external_dest_addrs = ['addrask'] * addrask + destaddrs
    for mix_offset in range(options.addrcount):
        srcmix = options.mixdepthsrc + options.mixdepthcount - mix_offset - 1
        for tx in reversed(tx_list):
            if tx['srcmixdepth'] == srcmix:
                tx['destination'] = external_dest_addrs[mix_offset]
                break
        if mix_offset == 0:
            # setting last mixdepth to send all to dest
            tx_list_remove = []
            for tx in tx_list:
                if tx['srcmixdepth'] == srcmix:
                    if tx['destination'] == 'internal':
                        tx_list_remove.append(tx)
                    else:
                        tx['amount_fraction'] = 1.0
            [tx_list.remove(t) for t in tx_list_remove]
    return tx_list
Beispiel #2
0
def generate_tumbler_tx(destaddrs, options):
    # sends the coins up through a few mixing depths
    # send to the destination addresses from different mixing depths

    # simple algo, move coins completely from one mixing depth to the next
    # until you get to the end, then send to destaddrs

    # txcounts for going completely from one mixdepth to the next
    # follows a normal distribution
    txcounts = rand_norm_array(options.txcountparams[0],
                               options.txcountparams[1], options.mixdepthcount)
    txcounts = lower_bounded_int(txcounts, options.mintxcount)
    tx_list = []
    for m, txcount in enumerate(txcounts):
        if options.mixdepthcount - options.addrcount <= m and m < \
                options.mixdepthcount - 1:
            #these mixdepths send to a destination address, so their
            # amount_fraction cant be 1.0, some coins must be left over
            if txcount == 1:
                txcount = 2
        # assume that the sizes of outputs will follow a power law
        amount_fractions = rand_pow_array(options.amountpower, txcount)
        amount_fractions = [1.0 - x for x in amount_fractions]
        amount_fractions = [
            x / sum(amount_fractions) for x in amount_fractions
        ]
        # transaction times are uncorrelated
        # time between events in a poisson process followed exp
        waits = rand_exp_array(options.timelambda, txcount)
        # number of makers to use follows a normal distribution
        makercounts = rand_norm_array(options.makercountrange[0],
                                      options.makercountrange[1], txcount)
        makercounts = lower_bounded_int(makercounts, options.minmakercount)
        if m == options.mixdepthcount - options.addrcount and options.donateamount:
            tx_list.append({
                'amount_fraction': 0,
                'wait': round(waits[0], 2),
                'srcmixdepth': m + options.mixdepthsrc,
                'makercount': makercounts[0],
                'destination': 'internal'
            })
        for amount_fraction, wait, makercount in zip(amount_fractions, waits,
                                                     makercounts):
            tx = {
                'amount_fraction': amount_fraction,
                'wait': round(wait, 2),
                'srcmixdepth': m + options.mixdepthsrc,
                'makercount': makercount,
                'destination': 'internal'
            }
            tx_list.append(tx)

    addrask = options.addrcount - len(destaddrs)
    external_dest_addrs = ['addrask'] * addrask + destaddrs
    for mix_offset in range(options.addrcount):
        srcmix = options.mixdepthsrc + options.mixdepthcount - mix_offset - 1
        for tx in reversed(tx_list):
            if tx['srcmixdepth'] == srcmix:
                tx['destination'] = external_dest_addrs[mix_offset]
                break
        if mix_offset == 0:
            # setting last mixdepth to send all to dest
            tx_list_remove = []
            for tx in tx_list:
                if tx['srcmixdepth'] == srcmix:
                    if tx['destination'] == 'internal':
                        tx_list_remove.append(tx)
                    else:
                        tx['amount_fraction'] = 1.0
            [tx_list.remove(t) for t in tx_list_remove]
    return tx_list