def get_prime_input_address(self, txid):
        url = '{api_url}/rawtx/{txid}'.format(api_url=self.url, txid=txid)
        try:
            LOG.info('GET %s' % url)
            r = requests.get(url)
            data = r.json()
        except Exception as ex:
            LOG.error(
                'Unable to get prime input address of tx %s from Blockchain.info: %s'
                % (txid, ex))
            return {
                'error':
                'Unable to get prime input address of tx %s from Blockchain.info'
                % txid
            }

        if 'inputs' in data:
            tx_inputs = data['inputs']

            input_addresses = []
            for i in range(0, len(tx_inputs)):
                if 'prev_out' in tx_inputs[
                        i]:  # Coinbase transactions don't have a input address
                    input_addresses.append(tx_inputs[i]['prev_out']['addr'])

            if len(input_addresses) > 0:
                prime_input_address = sorted(input_addresses)[0]
                return {'prime_input_address': prime_input_address}
            else:
                # transaction was a coinbase transaction, so there are no input addresses
                return {'prime_input_address': None}

        return {'error': 'Received invalid data: %s' % data}
Beispiel #2
0
    def get_balance(self, address):
        url = '{api_url}/address/{address}'.format(api_url=self.url,
                                                   address=address)
        try:
            LOG.info('GET %s' % url)
            r = requests.get(url)
            data = r.json()
        except Exception as ex:
            LOG.error(
                'Unable to get balance of address %s from Blocktrail.com: %s' %
                (address, ex))
            return {
                'error':
                'Unable to get balance of address %s from Blocktrail.com' %
                address
            }

        data = data['data'] if data['data'] is not None else {}

        if all(key in data for key in ('balance', 'received', 'sent')):
            balance = {
                'final':
                data['balance'] - data['unconfirmed_received'] +
                data['unconfirmed_sent'],
                'received':
                data['received'] - data['unconfirmed_received'],
                'sent':
                data['sent'] - data['unconfirmed_sent']
            }
            return {'balance': balance}
        else:
            return {'error': 'Received invalid data: %s' % data}
Beispiel #3
0
    def configure(self, **config):
        super(DeadMansSwitchTrigger, self).configure(**config)

        if 'timeout' in config and valid_amount(config['timeout']):
            self.timeout = config['timeout']

        if 'warning_email' in config and valid_email(config['warning_email']):
            self.warning_email = config['warning_email']

        if 'phase' in config and valid_phase(config['phase']):
            self.phase = config['phase']

        if 'activation_time' in config and valid_timestamp(
                config['activation_time']):
            self.activation_time = config['activation_time']

        if 'reset' in config and config['reset'] is True:
            self.triggered = False
            self.status = 'Active'

            # Reset a Dead Man's Switch trigger if needed
            if self.activation_time is not None and self.timeout is not None and self.phase >= 1:
                self.activation_time = int(time.time()) + self.timeout
                self.phase = 1
                LOG.info(
                    "Dead Man's Switch %s has been reset, will activate in %s seconds on %s"
                    % (self.id, self.timeout,
                       datetime.fromtimestamp(self.activation_time)))
Beispiel #4
0
    def get_block_by_hash(self, block_hash):
        url = '{api_url}/block/{hash}'.format(api_url=self.url,
                                              hash=block_hash)
        try:
            LOG.info('GET %s' % url)
            r = requests.get(url)
            data = r.json()
        except Exception as ex:
            LOG.error('Unable to get block %s from Blocktrail.com: %s' %
                      (block_hash, ex))
            return {
                'error':
                'Unable to get block %s from Blocktrail.com' % block_hash
            }
        data = data['data'] if data['data'] is not None else {}

        if all(key in data for key in ('height', 'hash', 'timestamp',
                                       'mrkl_root', 'size')):
            block = {
                'height': data['height'],
                'hash': data['hash'],
                'time': data['timestamp'],
                'merkleroot': data['mrkl_root'],
                'size': data['size']
            }

            return {'block': block}
        else:
            return {'error': 'Received invalid data: %s' % data}
    def get_block_by_height(self, height):
        url = '{api_url}/get_block/{network}/{height}'.format(
            api_url=self.url, network=self.network, height=height)
        try:
            LOG.info('GET %s' % url)
            r = requests.get(url)
            data = r.json()
        except Exception as ex:
            LOG.error('Unable to get block %s from Chain.so: %s' %
                      (height, ex))
            return {'error': 'Unable to get block %s from Chain.so' % height}

        if 'data' not in data:
            LOG.error('Invalid response data from Chain.so: %s' % data)
            return {'error': 'Invalid response data from Chain.so: %s' % data}

        data = data['data']

        if all(key in data for key in ('block_no', 'blockhash', 'time',
                                       'merkleroot', 'size')):
            block = {
                'height': data['block_no'],
                'hash': data['blockhash'],
                'time': data['time'],
                'merkleroot': data['merkleroot'],
                'size': data['size']
            }
            return {'block': block}
        else:
            return {'error': 'Received invalid data: %s' % data}
    def get_block_by_hash(self, block_hash):
        url = self.url + '/block/' + block_hash
        try:
            LOG.info('GET %s' % url)
            r = requests.get(url)
            data = r.json()
        except Exception as ex:
            LOG.error('Unable to get block %s from %s: %s' %
                      (block_hash, self.url, ex))
            return {
                'error':
                'Unable to get block %s from %s' % (block_hash, self.url)
            }

        block = {}
        if all(key in data
               for key in ('height', 'hash', 'time', 'merkleroot', 'size')):
            block['height'] = data['height']
            block['hash'] = data['hash']
            block['time'] = data['time']
            block['merkleroot'] = data['merkleroot']
            block['size'] = data['size']
            return {'block': block}
        else:
            return {'error': 'Received invalid data: %s' % data}
    def get_prime_input_address(self, txid):
        url = self.url + '/tx/' + str(txid)
        try:
            LOG.info('GET %s' % url)
            r = requests.get(url)
            data = r.json()
        except Exception as ex:
            LOG.error(
                'Unable to get prime input address of transaction %s from %s: %s'
                % (txid, self.url, ex))
            return {
                'error':
                'Unable to get prime input address of transaction %s from %s' %
                (txid, self.url)
            }

        if 'vin' in data:
            tx_inputs = data['vin']

            input_addresses = []
            for i in range(0, len(tx_inputs)):
                input_addresses.append(tx_inputs[i]['addr'])

            if len(input_addresses) > 0:
                prime_input_address = sorted(input_addresses)[0]
                return {'prime_input_address': prime_input_address}

        return {'error': 'Received invalid data: %s' % data}
    def get_balance(self, address):
        url = '{api_url}/address/{network}/{address}'.format(
            api_url=self.url, network=self.network, address=address)
        try:
            LOG.info('GET %s' % url)
            r = requests.get(url)
            data = r.json()
        except Exception as ex:
            LOG.error('Unable to get balance of address %s from Chain.so: %s' %
                      (address, ex))
            return {
                'error':
                'Unable to get balance of address %s from Chain.so' % address
            }

        if 'data' not in data:
            LOG.error('Invalid response data from Chain.so: %s' % data)
            return {'error': 'Invalid response data from Chain.so: %s' % data}

        data = data['data']

        final_balance = btc2satoshis(btc=data['balance'])
        received_balance = btc2satoshis(btc=data['received_value'])
        sent_balance = received_balance - final_balance

        balance = {
            'final': final_balance,
            'received': received_balance,
            'sent': sent_balance
        }

        return {'balance': balance}
    def get_utxos(self, address, confirmations=3):
        url = self.url + '/addrs/' + address + '/utxo?noCache=1'
        try:
            LOG.info('GET %s' % url)
            r = requests.get(url)
            data = r.json()
        except Exception as ex:
            LOG.error('Unable to get utxos of address %s from %s: %s' %
                      (address, url, ex))
            return {
                'error':
                'Unable to get utxos of address %s from %s' % (address, url)
            }

        utxos = []
        for output in data:
            if all(key in output for key in ('confirmations', 'txid', 'vout',
                                             'satoshis', 'scriptPubKey')):
                utxo = {
                    'confirmations': output['confirmations'],
                    'output_hash': output['txid'],
                    'output_n': output['vout'],
                    'value': output['satoshis'],
                    'script': output['scriptPubKey']
                }

                if utxo['confirmations'] >= confirmations:
                    utxos.append(utxo)

        return {
            'utxos':
            sorted(utxos,
                   key=lambda k:
                   (k['confirmations'], k['output_hash'], k['output_n']))
        }
def initialize_database(database, tables, user, password):
    # Try to make a connection, if the database does not exist yet, create the database and create the tables in it
    """
    Check if a database exists, if not create it

    :param database: The name of the database (string)
    :param tables: A dict containing the sql statements to create the tables (dict)
    :param user: The username for the database (string)
    :param password: The password for the database (string)
    """
    cnx = mysql.connector.connect(user=user, password=password)
    cursor = cnx.cursor()

    try:
        cursor.execute("USE {}".format(database))
    except mysql.connector.Error as err:
        LOG.info("Database {} does not exists.".format(database))
        if err.errno == errorcode.ER_BAD_DB_ERROR:
            create_database(cursor=cursor, database=database)
            LOG.info("Database {} created successfully.".format(database))
            cnx.database = database
            create_tables(cursor=cursor, tables=tables)
        else:
            LOG.error(err)

    cursor.close()
    cnx.close()
    def construct_transaction_inputs(self):
        """
        Construct a list of dict object containing the necessary information for the inputs of a transaction

        :return: A list of dicts containing the following keys for each utxo: 'address', 'value', 'output' and 'confirmations'
        """

        if self.unspent_outputs is not None and len(self.unspent_outputs) > 0:
            LOG.info('Found %s utxos for address %s' %
                     (len(self.unspent_outputs), self.sending_address))
        else:
            LOG.error('No utxos found for address %s' % self.sending_address)

        # Construct the transaction inputs
        tx_inputs = [
            {
                'address': utxo.address,
                'value': utxo.value,
                'output':
                utxo.output,  # output needs to be formatted as txid:i
                'confirmations': utxo.confirmations
            } for utxo in self.unspent_outputs
        ]

        return tx_inputs
Beispiel #12
0
    def get_block_by_hash(self, block_hash):
        url = self.url + '/block/{hash}'.format(hash=block_hash)
        LOG.info('GET %s' % url)
        try:
            r = requests.get(url)
            data = r.json()
        except Exception as ex:
            LOG.error('Unable to get block %s from Blockstream.info: %s' %
                      (block_hash, ex))
            return {
                'error':
                'Unable to get block %s from Blockstream.info' % block_hash
            }

        if all(key in data for key in ('height', 'id', 'timestamp',
                                       'merkle_root', 'size')):
            block = {
                'height': data['height'],
                'hash': data['id'],
                'time': data['timestamp'],
                'merkleroot': data['merkle_root'],
                'size': data['size']
            }  # Todo weight?
            return {'block': block}
        else:
            return {'error': 'Received invalid data: %s' % data}
    def log_transaction_info(self, tx_inputs, tx_outputs):
        """
        Write information about the transaction in the logs

        :param tx_inputs: The transaction inputs
        :param tx_outputs: The transaction outputs
        """
        if self.amount == 0:
            LOG.info('New %s transaction: sending ALL available funds' %
                     self.transaction_type)
        else:
            LOG.info('New %s transaction: sending %s satoshis' %
                     (self.transaction_type, self.amount))

        for tx_input in tx_inputs:
            LOG.info(
                'INPUT: %s -> %s (%s)' %
                (tx_input['address'], tx_input['value'], tx_input['output']))

        for tx_output in tx_outputs:
            LOG.info('OUTPUT: %s -> %s' %
                     (tx_output['address'], tx_output['value']))

        if self.op_return_data is not None:
            LOG.info('OUTPUT: OP_RETURN -> %s' % self.op_return_data)
Beispiel #14
0
    def get_balance(self, address):
        url = self.url + '/address/{address}'.format(address=address)
        LOG.info('GET %s' % url)
        try:
            r = requests.get(url)
            data = r.json()
        except Exception as ex:
            LOG.error(
                'Unable to get address info for %s from Blockstream.info: %s' %
                (address, ex))
            return {
                'error':
                'Unable to get address info for %s from Blockstream.info' %
                address
            }

        sent_balance = data['chain_stats'][
            'spent_txo_sum']  # Todo fix the sent and received balance because blockstream reports this wrong (also counts when change is sent back to the address itself)
        received_balance = data['chain_stats']['funded_txo_sum']
        final_balance = received_balance - sent_balance

        balance = {
            'final': final_balance,
            'received': received_balance,
            'sent': sent_balance
        }
        return {'balance': balance}
    def get_block_by_height(self, height):
        url = '{api_url}/block-height/{height}?format=json'.format(
            api_url=self.url, height=height)
        try:
            LOG.info('GET %s' % url)
            r = requests.get(url)
            data = r.json()
        except Exception as ex:
            LOG.error('Unable to get block %s from Blockchain.info: %s' %
                      (height, ex))
            return {
                'error': 'Unable to get block %s from Blockchain.info' % height
            }

        if 'blocks' in data:
            blocks = data['blocks']
            for i in range(0, len(blocks)):
                if blocks[i]['main_chain'] is True and blocks[i][
                        'height'] == height:
                    block = {
                        'height': blocks[i]['height'],
                        'hash': blocks[i]['hash'],
                        'time': blocks[i]['time'],
                        'merkleroot': blocks[i]['mrkl_root'],
                        'size': blocks[i]['size']
                    }
                    return {'block': block}

        return {'error': 'Received invalid data: %s' % data}
Beispiel #16
0
    def decorated_function(*args, **kwargs):
        start_time = time.time()
        output = f(*args, **kwargs)
        end_time = time.time()

        LOG.info('Script runtime: %s seconds' % (end_time - start_time))

        return output
Beispiel #17
0
    def activate(self):
        super(RecurringTrigger, self).activate()

        if self.end_time is None or self.next_activation + self.interval <= self.end_time:
            self.next_activation += self.interval  # Todo what if trigger was activated after interval has passed??
            LOG.info('Setting next activation of recurring trigger %s to %s' %
                     (self.id, datetime.fromtimestamp(self.next_activation)))
            self.save()
    def __exit__(self, exc_type, exc_val, exc_tb):
        # Make sure data is committed to the database
        if self.commit is True:
            LOG.info('Committing data')
            self.cnx.commit()

        LOG.info('Closing mysql cursor')
        self.cursor.close()
        self.cnx.close()
 def __enter__(self):
     LOG.info('Creating mysql cursor to database %s @ %s:%s' %
              (self.database, self.host, self.port))
     self.cnx = mysql.connector.connect(user=self.user,
                                        password=self.password,
                                        database=self.database,
                                        host=self.host,
                                        port=self.port)
     self.cursor = self.cnx.cursor()
     return self.cursor
    def run(self):
        """
        Run the action

        :return: True upon success, False upon failure
        """
        LOG.info('Allowing reveal of RevealSecret action %s' % self.id)
        self.allow_reveal = True
        self.save()
        return True
Beispiel #21
0
    def run(self, *args, **kwargs):
        LOG.info('Running Spellbook Script: %s' %
                 os.path.splitext(os.path.basename(__file__))[0])

        if 'message' not in self.json:
            LOG.error('key "message" not found in http POST request')
            return

        message = self.json['message']

        if not valid_op_return(message=message):
            LOG.error(
                'Can not create Notary request: message is not valid to put in a OP_RETURN output: %s'
                % message)
            return

        # Use the number of times the trigger has been triggered as a identifier for the request and as the index of the address in the hot wallet
        request_id = self.triggered + 1

        # Get the address to receive payment
        request_address = get_address_from_wallet(account=BIP44_ACCOUNT,
                                                  index=request_id)

        # Create a new action to send a custom transaction with the OP_RETURN data
        action_id = 'Notary-send-tx_%s' % request_id
        action = get_action(action_id=action_id,
                            action_type=ActionType.SENDTRANSACTION)
        action.transaction_type = TransactionType.SEND2SINGLE
        action.wallet_type = WALLET_TYPE
        action.bip44_account = BIP44_ACCOUNT
        action.bip44_index = request_id
        action.receiving_address = get_address_from_wallet(
            account=BIP44_ACCOUNT, index=0
        )  # always use the first address in the account to receive the transactions
        action.op_return_data = message
        action.save()

        # Create a new trigger that activates when payment is received
        invoice_paid_trigger_id = 'Notary-payment_%s' % request_id
        trigger = get_trigger(trigger_id=invoice_paid_trigger_id,
                              trigger_type=TriggerType.BALANCE)
        trigger.address = request_address
        trigger.amount = NOTARY_COST
        trigger.actions = [action_id]
        trigger.status = 'Active'
        trigger.self_destruct = int(time.time()) + REQUEST_TIMEOUT
        trigger.destruct_actions = True
        trigger.save()

        self.http_response = {
            'request_id': request_id,
            'address': request_address,
            'value': NOTARY_COST,
            'timeout': int(time.time()) + REQUEST_TIMEOUT
        }
Beispiel #22
0
    def get_transaction(self, txid):
        url = '{api_url}/tx/{txid}?verbose=3'.format(api_url=self.url,
                                                     txid=txid)
        try:
            LOG.info('GET %s' % url)
            r = requests.get(url)
            data = r.json()
        except Exception as ex:
            LOG.error('Unable to get transaction %s from BTC.com: %s' %
                      (txid, ex))
            return {
                'error': 'Unable to get transaction %s from BTC.com' % txid
            }

        data = data['data'] if data['data'] is not None else {}

        # todo check key names , test by setting testnet wrong on explorers
        tx = TX()
        tx.txid = txid
        tx.wtxid = data['witness_hash']
        tx.lock_time = data['lock_time']
        tx.block_height = data[
            'block_height'] if 'block_height' in data and data[
                'block_height'] != -1 else None
        tx.confirmations = data[
            'confirmations'] if 'confirmations' in data else None

        for item in data['inputs']:
            tx_input = TxInput()
            tx_input.address = item['prev_addresses'][0] if len(
                item['prev_addresses']) > 0 else None
            tx_input.value = item['prev_value']
            tx_input.txid = item['prev_tx_hash']
            tx_input.n = item['prev_position'] if item[
                'prev_position'] is not -1 else None
            tx_input.script = item['script_hex']
            tx_input.sequence = item['sequence']

            tx.inputs.append(tx_input)

        for i, item in enumerate(data['outputs']):
            tx_output = TxOutput()
            tx_output.address = item['addresses'][0] if len(
                item['addresses']) > 0 else None
            tx_output.value = item['value']
            tx_output.n = i
            tx_output.spent = False if item['spent_by_tx'] is None else True
            tx_output.script = item['script_hex']

            if item['script_hex'][:2] == '6a':
                tx_output.op_return = tx.decode_op_return(item['script_hex'])

            tx.outputs.append(tx_output)

        return {'transaction': tx.json_encodable()}
def connect_to_ipfs():
    global IPFS_API

    # Check if IPFS node is running
    multi_address = '/ip4/{host}/tcp/{port}/http'.format(
        host=get_ipfs_api_host(), port=get_ipfs_api_port())
    LOG.info('Trying to connect with IPFS on %s' % multi_address)
    try:
        IPFS_API = ipfshttpclient.connect(multi_address)
        LOG.info('Connected with IPFS')
    except Exception as ex:
        LOG.error('IPFS node is not running: %s' % ex)
    def get_transaction(self, txid):
        url = self.url + '/tx/' + str(txid)
        try:
            LOG.info('GET %s' % url)
            r = requests.get(url)
            data = r.json()
        except Exception as ex:
            LOG.error('Unable to get transaction %s from %s: %s' %
                      (txid, self.url, ex))
            return {
                'error':
                'Unable to get transaction %s from %s' % (txid, self.url)
            }

        tx = TX()
        tx.txid = txid
        tx.block_height = data['blockheight'] if 'blockheight' in data else None
        tx.lock_time = data['locktime']

        for item in data['vin']:
            tx_input = TxInput()
            tx_input.address = item['addr'] if 'addr' in item else None
            tx_input.value = item['valueSat'] if 'valueSat' in item else 0
            tx_input.txid = item['txid'] if 'txid' in item else None
            tx_input.n = item['n'] if 'coinbase' not in item else None
            tx_input.script = item['scriptSig'][
                'hex'] if 'scriptSig' in item else None
            if 'coinbase' in item:
                tx_input.script = item['coinbase']
            tx_input.sequence = item['sequence']

            tx.inputs.append(tx_input)

        for item in data['vout']:
            tx_output = TxOutput()
            tx_output.address = item['scriptPubKey']['addresses'][
                0] if 'addresses' in item['scriptPubKey'] else None
            tx_output.value = int(float(item['value']) * 1e8)
            tx_output.n = item['n']
            tx_output.spent = True if 'spentTxId' in item and item[
                'spentTxId'] is not None else False
            tx_output.script = item['scriptPubKey']['hex']
            if item['scriptPubKey']['hex'][:2] == '6a':
                tx_output.op_return = tx.decode_op_return(
                    item['scriptPubKey']['hex'])

            tx.outputs.append(tx_output)

        tx.confirmations = data[
            'confirmations'] if 'confirmations' in data else None

        return {'transaction': tx.json_encodable()}
Beispiel #25
0
    def load_script(self):
        if self.script is not None:
            if not valid_script(self.script):
                return

            script_name = self.script[:
                                      -3]  # script name without the .py extension
            script_path = None
            script_module_name = None

            # Search for the script in the allowed root directories
            for root_dir in ['spellbookscripts', 'apps']:
                if os.path.isfile(os.path.join(root_dir, self.script)):
                    script_path = os.path.join(root_dir, self.script)
                    if platform.system() == 'Windows':
                        script_module_name = '%s.%s' % (
                            root_dir, script_name.replace('\\', '.'))
                    elif platform.system() == 'Linux':
                        script_module_name = '%s.%s' % (
                            root_dir, script_name.replace('/', '.'))
                    else:
                        raise NotImplementedError(
                            'Unsupported platform: only windows and linux are supported'
                        )

            if script_path is None:
                LOG.error('Can not find spellbook script %s' % self.script)
                return

            LOG.info('Loading Spellbook Script %s' % script_path)
            LOG.info('Script module: %s (%s)' %
                     (script_module_name, type(script_module_name)))
            try:
                script_module = importlib.import_module(script_module_name)
            except Exception as ex:
                LOG.error('Failed to load Spellbook Script %s: %s' %
                          (script_path, ex))
                return

            script_class_name = os.path.basename(script_path)[:-3]
            spellbook_script = getattr(script_module, script_class_name)
            kwargs = self.get_script_variables()
            script = spellbook_script(**kwargs)

            if not isinstance(script, SpellbookScript):
                LOG.error(
                    'Script %s is not a valid Spellbook Script, instead it is a %s'
                    % (self.script, type(script)))
                return

            return script
Beispiel #26
0
    def parse_transaction(self, data, latest_block_height=None):
        if latest_block_height is None:
            url = self.url + '/blocks/tip/height'
            LOG.info('GET %s' % url)
            try:
                r = requests.get(url)
                latest_block_height = int(r.text)
            except Exception as ex:
                LOG.error(
                    'Unable to get latest block_height from Blockstream.info: %s'
                    % ex)
                return {
                    'error':
                    'Unable to get latest block_height from Blockstream.info'
                }

        tx = TX()
        tx.txid = data['txid']
        tx.lock_time = data['locktime']
        tx.block_height = data['status'][
            'block_height'] if 'block_height' in data['status'] else None
        tx.confirmations = latest_block_height - tx.block_height + 1 if tx.block_height is not None else 0

        for item in data['vin']:
            tx_input = TxInput()
            tx_input.address = item['prevout']['scriptpubkey_address'] if item[
                'prevout'] is not None else None
            tx_input.value = item['prevout']['value'] if item[
                'prevout'] is not None else 0
            tx_input.n = item['vout'] if item['is_coinbase'] is False else None
            tx_input.txid = item['txid']
            tx_input.script = item['scriptsig']
            tx_input.sequence = item['sequence']

            tx.inputs.append(tx_input)

        for i, item in enumerate(data['vout']):
            tx_output = TxOutput()
            tx_output.address = item[
                'scriptpubkey_address'] if 'scriptpubkey_address' in item else None
            tx_output.value = item['value']
            tx_output.n = i
            tx_output.spent = None  # Blockstream does not provide information if a tx output has been spent
            tx_output.script = item['scriptpubkey']
            if item['scriptpubkey'][:2] == '6a':
                tx_output.op_return = tx.decode_op_return(item['scriptpubkey'])

            tx.outputs.append(tx_output)

        return tx
Beispiel #27
0
    def conditions_fulfilled(self):
        if self.interval is None or self.begin_time is None:
            return False

        if self.end_time is None:
            return self.next_activation <= int(time.time())

        elif self.end_time <= int(time.time()):
            LOG.info('Recurring trigger %s has reached its end time' % self.id)
            self.status = 'Succeeded'
            self.save()
            return False

        return self.next_activation <= int(time.time()) <= self.end_time
def create_database(cursor, database):
    """
    Create a new database

    :param cursor: A MySQL cursor object
    :param database: The name of the database (string)
    """
    LOG.info('Creating database %s' % database)

    try:
        cursor.execute(
            "CREATE DATABASE {} DEFAULT CHARACTER SET 'utf8'".format(database))
    except mysql.connector.Error as err:
        LOG.error("Failed creating database: {}".format(err))
def check_triggers(trigger_id=None):
    # Get a list of all trigger_ids that are configured
    triggers = get_triggers()

    # If a trigger_id is given, only check that specific trigger
    if trigger_id is not None and trigger_id in triggers:
        triggers = [trigger_id]
    elif trigger_id is not None and trigger_id not in triggers:
        return {'error': 'Unknown trigger id: %s' % trigger_id}

    for trigger_id in triggers:
        trigger = get_trigger(trigger_id=trigger_id)
        if trigger.status == 'Active':
            LOG.info('Checking conditions of trigger %s' % trigger_id)
            if trigger.conditions_fulfilled() is True:
                trigger.activate()

        if trigger.self_destruct is not None:
            if trigger.self_destruct <= int(time.time()):
                LOG.info('Trigger %s has reached its self-destruct time' %
                         trigger_id)

                # Also destruct any attached actions if needed
                if trigger.destruct_actions is True:
                    for action_id in trigger.actions:
                        LOG.info('Deleting action %s' % action_id)
                        delete_action(action_id=action_id)

                LOG.info('Deleting trigger %s' % trigger_id)
                delete_trigger(trigger_id=trigger_id)
                continue
    def push_tx(self, tx):
        url = '{api_url}/pushtx'.format(api_url=self.url)
        LOG.info('POST %s' % url)
        try:
            r = requests.post(url, data=dict(tx=tx))
        except Exception as ex:
            LOG.error('Unable to push tx via Blockchain.info: %s' % ex)
            return {'error': 'Unable to push tx Blockchain.info: %s' % ex}

        data = r.text.strip()
        if r.status_code == 200 and data == 'Transaction Submitted':
            return {'success': True}
        else:
            LOG.error('Unable to push tx via Blockchain.info: %s' % data)
            return {'error': 'Unable to push tx Blockchain.info: %s' % data}