Browse Source
3bc3c93 Add yg-privacyenhanced, a yield generator randomizing most values to make blockchain analysis harder (Alex Cato)
master
1 changed files with 97 additions and 0 deletions
@ -0,0 +1,97 @@ |
|||||||
|
#! /usr/bin/env python |
||||||
|
from __future__ import absolute_import, print_function |
||||||
|
|
||||||
|
import random |
||||||
|
|
||||||
|
from jmclient import (YieldGenerator, YieldGeneratorBasic, ygmain, get_log, |
||||||
|
jm_single, calc_cj_fee) |
||||||
|
|
||||||
|
# This is a maker for the purposes of generating a yield from held bitcoins |
||||||
|
# while maximising the difficulty of spying on blockchain activity. |
||||||
|
# This is primarily attempted by randomizing all aspects of orders |
||||||
|
# after transactions wherever possible. |
||||||
|
|
||||||
|
"""THESE SETTINGS CAN SIMPLY BE EDITED BY HAND IN THIS FILE: |
||||||
|
""" |
||||||
|
|
||||||
|
ordertype = 'swreloffer' # [string, 'swreloffer' or 'swabsoffer'] / which fee type to actually use |
||||||
|
cjfee_a = 5000 # [satoshis, any integer] / absolute offer fee you wish to receive for coinjoins (cj) |
||||||
|
cjfee_r = '0.0002' # [percent, any str between 0-1] / relative offer fee you wish to receive based on a cj's amount |
||||||
|
cjfee_factor = 0.1 # [percent, 0-1] / variance around the average fee. Ex: 200 fee, 0.2 var = fee is btw 160-240 |
||||||
|
txfee = 1000 # [satoshis, any integer] / the average transaction fee you're adding to coinjoin transactions |
||||||
|
txfee_factor = 0.3 # [percent, 0-1] / variance around the average fee. Ex: 1000 fee, 0.2 var = fee is btw 800-1200 |
||||||
|
minsize = 1000000 # [satoshis, any integer] / minimum size of your cj offer. Lower cj amounts will be disregarded |
||||||
|
size_factor = 0.1 # [percent, 0-1] / variance around all offer sizes. Ex: 500k minsize, 0.1 var = 450k-550k |
||||||
|
gaplimit = 6 |
||||||
|
|
||||||
|
# end of settings customization |
||||||
|
|
||||||
|
jlog = get_log() |
||||||
|
|
||||||
|
class YieldGeneratorPrivacyEnhanced(YieldGeneratorBasic): |
||||||
|
|
||||||
|
def __init__(self, wallet, offerconfig): |
||||||
|
self.txfee, self.cjfee_a, self.cjfee_r, self.ordertype, self.minsize \ |
||||||
|
= offerconfig |
||||||
|
super(YieldGeneratorPrivacyEnhanced, self).__init__(wallet, offerconfig) |
||||||
|
|
||||||
|
def create_my_orders(self): |
||||||
|
mix_balance = self.wallet.get_balance_by_mixdepth() |
||||||
|
# We publish ONLY the maximum amount and use minsize for lower bound; |
||||||
|
# leave it to oid_to_order to figure out the right depth to use. |
||||||
|
f = '0' |
||||||
|
if ordertype == 'swreloffer': |
||||||
|
f = self.cjfee_r |
||||||
|
elif ordertype == 'swabsoffer': |
||||||
|
f = str(self.txfee + self.cjfee_a) |
||||||
|
mix_balance = dict([(m, b) for m, b in mix_balance.iteritems() |
||||||
|
if b > self.minsize]) |
||||||
|
if len(mix_balance) == 0: |
||||||
|
jlog.error('You do not have the minimum required amount of coins' |
||||||
|
' to be a maker: ' + str(minsize)) |
||||||
|
return [] |
||||||
|
max_mix = max(mix_balance, key=mix_balance.get) |
||||||
|
|
||||||
|
# randomizing the different values |
||||||
|
randomize_txfee = int(random.uniform(txfee * (1 - float(txfee_factor)), |
||||||
|
txfee * (1 + float(txfee_factor)))) |
||||||
|
randomize_minsize = int(random.uniform(self.minsize * (1 - float(size_factor)), |
||||||
|
self.minsize * (1 + float(size_factor)))) |
||||||
|
possible_maxsize = mix_balance[max_mix] - max(jm_single().DUST_THRESHOLD, randomize_txfee) |
||||||
|
randomize_maxsize = int(random.uniform(possible_maxsize * (1 - float(size_factor)), |
||||||
|
possible_maxsize)) |
||||||
|
|
||||||
|
if ordertype == 'swabsoffer': |
||||||
|
randomize_cjfee = int(random.uniform(float(cjfee_a) * (1 - float(cjfee_factor)), |
||||||
|
float(cjfee_a) * (1 + float(cjfee_factor)))) |
||||||
|
randomize_cjfee = randomize_cjfee + randomize_txfee |
||||||
|
else: |
||||||
|
randomize_cjfee = random.uniform(float(f) * (1 - float(cjfee_factor)), |
||||||
|
float(f) * (1 + float(cjfee_factor))) |
||||||
|
randomize_cjfee = "{0:.6f}".format(randomize_cjfee) # round to 6 decimals |
||||||
|
|
||||||
|
order = {'oid': 0, |
||||||
|
'ordertype': self.ordertype, |
||||||
|
'minsize': randomize_minsize, |
||||||
|
'maxsize': randomize_maxsize, |
||||||
|
'txfee': randomize_txfee, |
||||||
|
'cjfee': str(randomize_cjfee)} |
||||||
|
|
||||||
|
# sanity check |
||||||
|
assert order['minsize'] >= 0 |
||||||
|
assert order['maxsize'] > 0 |
||||||
|
assert order['minsize'] <= order['maxsize'] |
||||||
|
if order['ordertype'] == 'swreloffer': |
||||||
|
while order['txfee'] >= (float(order['cjfee']) * order['minsize']): |
||||||
|
order['txfee'] = int(order['txfee'] / 2) |
||||||
|
jlog.info('Warning: too high txfee to be profitable, halfing it to: ' + str(order['txfee'])) |
||||||
|
|
||||||
|
return [order] |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
ygmain(YieldGeneratorPrivacyEnhanced, txfee=txfee, cjfee_a=cjfee_a, |
||||||
|
cjfee_r=cjfee_r, ordertype=ordertype, |
||||||
|
nickserv_password='', |
||||||
|
minsize=minsize, gaplimit=gaplimit) |
||||||
|
print('done') |
||||||
Loading…
Reference in new issue