<commit_before>#!/usr/bin/env python

from gevent import Greenlet, monkey, core; monkey.patch_all()

import bottle, bitcoinrpc.authproxy, math, sys
import logging, logging.config

try:
    from recaptcha.client import captcha
except ImportError:
    captcha = None

try:
    import qrcode
except ImportError:
    qrcode = None

class DuplicateKeyError(Exception):
    pass

def c_bool(orig):
    '''Convert a config value to a boolean value, or die trying'''
    norm = orig.lower().strip()
    if norm in ('yes', 'y', 'true', 't', '1'):
        return True
    if norm in ('no', 'n', 'false', 'f', '0'):
        return False
    raise TypeError

class CoinBank(object):
    def __init__(self, config):
        self.url       = config['rpc.url']
        self.acct      = config['faucet.acct']
        self.ratio     = float(config['faucet.ratio'])
        self.txfee     = float(config['faucet.txfee'])
        self.interval  = float(config['faucet.interval'])
        self.max_pay   = float(config['faucet.max_payout'])
        self.qr_regen  = c_bool(config['qrcode.generate'])
        self.qr_path   = config['qrcode.path']
        self.qr_file   = config['qrcode.file']

        svc = self.get_proxy()

        try:
            reuse_addr = config['faucet.reuse_addr']
            self.reuse_addr = c_bool(reuse_addr)
            self._public_address = False
        except TypeError:
            self.reuse_addr = True
            if svc.validateaddress(reuse_addr)['isvalid']:
                self._public_address = reuse_addr
            else:
                raise ValueError

        logging.config.fileConfig(config['logging.config_file'])
        self.log = logging.getLogger('CoinBank')

        self.pending = {}
        self.paid = [(0,0)]
        self.pay_periods = 0
        self.last_pay_time = core.time()

        self._balance_stat = 0
        self._balance = self.balance

        self._public_address_stat = 0
        self._public_address = self.public_address

        self._all_addresses_stat = 0
        self._all_addresses = self.all_addresses

        self.coin, self.symbol = {
            '1': ('BTC',  u'\u0243'),
            'L': ('LTC',  u'\u0141'),
            'D': ('DOGE', u'\u0189'),
            'N': ('NAME', u'\u2115'),
            'P': ('PPC',  u'\u2C63'),
            'm': ('test-coin', u'\u0166'),
            'n': ('test-coin', u'\u0166'),
        }.get(self.public_address[0], ('UNK', '?'))

        if 'recaptcha.pub_key' in config:
            if captcha:
                self.captcha_html =  captcha.displayhtml(config['recaptcha.pub_key'])
                self.captcha_priv_key = config['recaptcha.priv_key']
            else:
                raise Exception("Can't use api keys: failed to import from recaptcha.client")
        else:
            self.captcha_html =  ''
            self.captcha_priv_key = None

        svc.settxfee(self.txfee)

        self.log.info('Started new CoinBank instance (%s)', self.coin)

    @property
    def balance(self):
        svc = None
        while self._balance_stat != self.get_pay_status():
            if svc is None:
                svc = self.get_proxy()
            self._balance_stat = self.get_pay_status()
            self._balance = float(svc.getbalance(self.acct))
        return self._balance

    @property
    def public_address(self):
        svc = None
        if not (self.reuse_addr and self._public_address):
            while self._public_address_stat != self.get_pay_status():
                if svc is None:
                    svc = self.get_proxy()
                self._public_address_stat = self.get_pay_status()
                self._public_address = svc.getaccountaddress(self.acct)
                if self.qr_regen:
                    qr = qrcode.QRCode()
                    qr.add_data(self._public_address)
                    qr_img = qr.make_image()
                    qr_img.save(self.qr_path + '/' + self.qr_file)
        return self._public_address

    @property
    def all_addresses(self):
        svc = None
        while self._all_addresses_stat != self.get_pay_status():
            if svc is None:
                svc = self.get_proxy()
            self._all_addresses_stat = self.get_pay_status()
            self._all_addresses = svc.getaddressesbyaccount(self.acct)
        return self._all_addresses

    def get_total_tx_fee(self, ins=None, outs=None):
        '''Estimate the transaction fee given the number of inputs and outputs'''
        if ins is None:
            ins = len(self.all_addresses)
        if outs is None:
            outs = len(self.pending)
        sz = ins*149 + outs*34 + 10
        return math.ceil(sz / 1024.0) * self.txfee

    def get_proxy(self):
        return bitcoinrpc.authproxy.AuthServiceProxy(self.url)

    def get_total_pending(self):
        return sum(self.pending.values())<commit_msg>Fix transaction fee calculation<commit_after>#!/usr/bin/env python

from gevent import Greenlet, monkey, core; monkey.patch_all()

import bottle, bitcoinrpc.authproxy, math, sys
import logging, logging.config

try:
    from recaptcha.client import captcha
except ImportError:
    captcha = None

try:
    import qrcode
except ImportError:
    qrcode = None

class DuplicateKeyError(Exception):
    pass

def c_bool(orig):
    '''Convert a config value to a boolean value, or die trying'''
    norm = orig.lower().strip()
    if norm in ('yes', 'y', 'true', 't', '1'):
        return True
    if norm in ('no', 'n', 'false', 'f', '0'):
        return False
    raise TypeError

class CoinBank(object):
    def __init__(self, config):
        self.url       = config['rpc.url']
        self.acct      = config['faucet.acct']
        self.ratio     = float(config['faucet.ratio'])
        self.txfee     = float(config['faucet.txfee'])
        self.interval  = float(config['faucet.interval'])
        self.max_pay   = float(config['faucet.max_payout'])
        self.qr_regen  = c_bool(config['qrcode.generate'])
        self.qr_path   = config['qrcode.path']
        self.qr_file   = config['qrcode.file']

        svc = self.get_proxy()

        try:
            reuse_addr = config['faucet.reuse_addr']
            self.reuse_addr = c_bool(reuse_addr)
            self._public_address = False
        except TypeError:
            self.reuse_addr = True
            if svc.validateaddress(reuse_addr)['isvalid']:
                self._public_address = reuse_addr
            else:
                raise ValueError

        logging.config.fileConfig(config['logging.config_file'])
        self.log = logging.getLogger('CoinBank')

        self.pending = {}
        self.paid = [(0,0)]
        self.pay_periods = 0
        self.last_pay_time = core.time()

        self._balance_stat = 0
        self._balance = self.balance

        self._public_address_stat = 0
        self._public_address = self.public_address

        self._utxo_count_stat = 0
        self._utxo_count = self.utxo_count

        self.coin, self.symbol = {
            '1': ('BTC',  u'\u0243'),
            'L': ('LTC',  u'\u0141'),
            'D': ('DOGE', u'\u0189'),
            'N': ('NAME', u'\u2115'),
            'P': ('PPC',  u'\u2C63'),
            'm': ('test-coin', u'\u0166'),
            'n': ('test-coin', u'\u0166'),
        }.get(self.public_address[0], ('UNK', '?'))

        if 'recaptcha.pub_key' in config:
            if captcha:
                self.captcha_html =  captcha.displayhtml(config['recaptcha.pub_key'])
                self.captcha_priv_key = config['recaptcha.priv_key']
            else:
                raise Exception("Can't use api keys: failed to import from recaptcha.client")
        else:
            self.captcha_html =  ''
            self.captcha_priv_key = None

        svc.settxfee(self.txfee)

        self.log.info('Started new CoinBank instance (%s)', self.coin)

    @property
    def balance(self):
        svc = None
        while self._balance_stat != self.get_pay_status():
            if svc is None:
                svc = self.get_proxy()
            self._balance_stat = self.get_pay_status()
            self._balance = float(svc.getbalance(self.acct))
        return self._balance

    @property
    def public_address(self):
        svc = None
        if not (self.reuse_addr and self._public_address):
            while self._public_address_stat != self.get_pay_status():
                if svc is None:
                    svc = self.get_proxy()
                self._public_address_stat = self.get_pay_status()
                self._public_address = svc.getaccountaddress(self.acct)
                if self.qr_regen:
                    qr = qrcode.QRCode()
                    qr.add_data(self._public_address)
                    qr_img = qr.make_image()
                    qr_img.save(self.qr_path + '/' + self.qr_file)
        return self._public_address

    @property
    def utxo_count(self):
        svc = None
        while self._utxo_count_stat != self.get_pay_status():
            if svc is None:
                svc = self.get_proxy()
            self._utxo_count_stat = self.get_pay_status()
            addrs = set(svc.getaddressesbyaccount(self.acct))
            self._utxo_count = len([
                1 for utxo in svc.listunspent(1)
                if utxo['address'] in addrs
            ])
        return self._utxo_count

    def get_total_tx_fee(self, ins=None, outs=None):
        '''Estimate the transaction fee given the number of inputs and outputs'''
        if ins is None:
            ins = self.utxo_count
        if outs is None:
            outs = len(self.pending)
        sz = ins*149 + outs*34 + 10
        return math.ceil(sz / 1024.0) * self.txfee

    def get_proxy(self):
        return bitcoinrpc.authproxy.AuthServiceProxy(self.url)

    def get_total_pending(self):
        return sum(self.pending.values())
{'fraction_non_alphanumeric': 0.11689497716894977, 'fraction_numerical': 0.010147133434804667, 'mean_word_length': 1.9866666666666666, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2517598', 'n_tokens_mistral': 3193, 'n_tokens_neox': 3011, 'n_words': 637}