Example #1
0
def random_address_from_lsl(address,
                            xpub,
                            sil_block_height=0,
                            rng_block_height=0):
    if not valid_address(address):
        return {'error': 'Invalid address: %s' % address}

    if not valid_xpub(xpub):
        return {'error': 'Invalid xpub: %s' % xpub}

    return RandomAddress(address=address,
                         xpub=xpub,
                         sil_block_height=sil_block_height).get(
                             source='LSL', rng_block_height=rng_block_height)
Example #2
0
def get_lal(address, xpub, block_height=0):
    if not valid_address(address):
        return {'error': 'Invalid address: %s' % address}

    if not valid_xpub(xpub):
        return {'error': 'Invalid xpub: %s' % xpub}

    sil_data = get_sil(address, block_height)

    if 'SIL' in sil_data:
        sil = sil_data['SIL']
        linked_addresses = get_addresses_from_xpub(xpub, len(sil))

        lal = []
        for i in range(0, len(sil)):
            lal.append([sil[i][0], linked_addresses[i]])

        return {'LAL': lal}
    else:
        return {'error': 'Received invalid SIL data: %s' % sil_data}
    def configure(self, **config):
        """
        Configure the action with given config settings

        :param config: A dict containing the configuration settings
                       - config['fee_address']               : An address to send the spellbook fee to
                       - config['fee_percentage']            : The percentage to calculate the spellbook fee
                       - config['wallet_type']               : The type of wallet (Single or BIP44)
                       - config['sending_address']           : The address that will be sending the transaction
                       - config['bip44_account']             : An account number of a BIP44 wallet
                       - config['bip44_index']               : An index number of a BIP44 account
                       - config['receiving_address']         : The address to receive the transaction
                       - config['receiving_xpub']            : The xpub key to derive the receiving addresses from
                       - config['amount']                    : The amount to send
                       - config['minimum_amount']            : The minimum amount that needs to be available
                       - config['registration_address']      : An address used for the registration of a SIL, LBL, LRL or LSL
                       - config['registration_block_height'] : An block height used for the registration of a SIL
                       - config['registration_xpub']         : An xpub key used for the registration of a LBL, LRL or LSL
                       - config['distribution']              : A dict containing a distribution (each address should be a key in the dict with the value being the share)
        """
        super(SendTransactionAction, self).configure(**config)
        if 'fee_address' in config and valid_address(config['fee_address']):
            self.fee_address = config['fee_address']

        if 'fee_percentage' in config and valid_percentage(
                config['fee_percentage']):
            self.fee_percentage = config['fee_percentage']

        if 'wallet_type' in config and config['wallet_type'] in [
                'Single', 'BIP44'
        ]:
            self.wallet_type = config['wallet_type']

        if 'sending_address' in config and valid_address(
                config['sending_address']):
            self.sending_address = config['sending_address']

        if 'bip44_account' in config:
            self.bip44_account = config['bip44_account']

        if 'bip44_index' in config:
            self.bip44_index = config['bip44_index']

        if 'receiving_address' in config and valid_address(
                config['receiving_address']):
            self.receiving_address = config['receiving_address']

        if 'receiving_xpub' in config and valid_xpub(config['receiving_xpub']):
            self.receiving_xpub = config['receiving_xpub']

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

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

        if 'op_return_data' in config and valid_op_return(
                config['op_return_data']):
            self.op_return_data = config['op_return_data']

        if 'change_address' in config and valid_address(
                config['change_address']):
            self.receiving_address = config['change_address']

        if 'transaction_type' in config and valid_transaction_type(
                config['transaction_type']):
            self.transaction_type = config['transaction_type']

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

        if 'registration_address' in config and valid_address(
                config['registration_address']):
            self.registration_address = config['registration_address']

        if 'registration_block_height' in config and valid_block_height(
                config['registration_block_height']):
            self.registration_block_height = config[
                'registration_block_height']

        if 'registration_xpub' in config and valid_xpub(
                config['registration_xpub']):
            self.registration_xpub = config['registration_xpub']

        if 'distribution' in config and valid_distribution(
                config['distribution']):
            self.distribution = config['distribution']

        if 'tx_fee_type' in config and config['tx_fee_type'] in [
                'High', 'Medium', 'Low', 'Fixed'
        ]:
            self.tx_fee_type = config['tx_fee_type']

        if 'tx_fee' in config and valid_amount(
                config['tx_fee']) and self.tx_fee_type == 'Fixed':
            self.tx_fee = config['tx_fee']

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

        if 'private_key' in config and valid_private_key(
                private_key=config['private_key']):
            self.private_key = config['private_key']

        # fill in the address in case of a BIP44 hot wallet
        if self.wallet_type == 'BIP44':
            self.sending_address = get_address_from_wallet(
                self.bip44_account, self.bip44_index)
    def get_distribution(self, transaction_type, sending_amount):
        if not valid_amount(sending_amount) or sending_amount == 0:
            LOG.error(
                'Unable to get distribution: invalid sending_amount: %s' %
                sending_amount)
            raise Exception(
                'Unable to get distribution: invalid sending_amount: %s' %
                sending_amount)

        if transaction_type == 'Send2Single':
            if not valid_address(self.receiving_address):
                LOG.error(
                    'Unable to get distribution: invalid receiving_address: %s'
                    % self.receiving_address)
                raise Exception(
                    'Unable to get distribution: invalid receiving_address: %s'
                    % self.receiving_address)
            distribution = {self.receiving_address: sending_amount}

        elif transaction_type == 'Send2Many':
            if not valid_distribution(self.distribution):
                LOG.error(
                    'Unable to get distribution: invalid distribution: %s' %
                    self.distribution)
                raise Exception(
                    'Unable to get distribution: invalid distribution: %s' %
                    self.distribution)
            distribution = self.distribution

        elif transaction_type == 'Send2SIL':
            if not valid_address(self.registration_address):
                LOG.error(
                    'Unable to get distribution: invalid registration_address: %s'
                    % self.registration_address)
                raise Exception(
                    'Unable to get distribution: invalid registration_address: %s'
                    % self.registration_address)
            if not valid_block_height(self.registration_block_height):
                LOG.error(
                    'Unable to get distribution: invalid registration_block_height: %s'
                    % self.registration_block_height)
                raise Exception(
                    'Unable to get distribution: invalid registration_block_height: %s'
                    % self.registration_block_height)

            data = get_sil(address=self.registration_address,
                           block_height=self.registration_block_height)
            if 'SIL' not in data:
                LOG.error('Unable to get distribution: invalid SIL data: %s' %
                          data)
                raise Exception('Unable to get distribution: invalid SIL: %s' %
                                data)
            distribution = {
                recipient[0]: recipient[1]
                for recipient in data['SIL']
            }

        elif transaction_type == 'Send2LBL':
            if not valid_address(self.registration_address):
                LOG.error(
                    'Unable to get distribution: invalid registration_address: %s'
                    % self.registration_address)
                raise Exception(
                    'Unable to get distribution: invalid registration_address: %s'
                    % self.registration_address)
            if not valid_xpub(self.registration_xpub):
                LOG.error(
                    'Unable to get distribution: invalid registration_xpub: %s'
                    % self.registration_xpub)
                raise Exception(
                    'Unable to get distribution: invalid registration_xpub: %s'
                    % self.registration_xpub)
            if not valid_block_height(self.registration_block_height):
                LOG.error(
                    'Unable to get distribution: invalid registration_block_height: %s'
                    % self.registration_block_height)
                raise Exception(
                    'Unable to get distribution: invalid registration_block_height: %s'
                    % self.registration_block_height)

            data = get_lbl(address=self.registration_address,
                           xpub=self.registration_xpub,
                           block_height=self.registration_block_height)
            if 'LBL' not in data:
                LOG.error('Unable to get distribution: invalid LBL data: %s' %
                          data)
                raise Exception('Unable to get distribution: invalid LBL: %s' %
                                data)
            distribution = {
                recipient[0]: recipient[1]
                for recipient in data['LBL']
            }

        elif transaction_type == 'Send2LRL':
            if not valid_address(self.registration_address):
                LOG.error(
                    'Unable to get distribution: invalid registration_address: %s'
                    % self.registration_address)
                raise Exception(
                    'Unable to get distribution: invalid registration_address: %s'
                    % self.registration_address)
            if not valid_xpub(self.registration_xpub):
                LOG.error(
                    'Unable to get distribution: invalid registration_xpub: %s'
                    % self.registration_xpub)
                raise Exception(
                    'Unable to get distribution: invalid registration_xpub: %s'
                    % self.registration_xpub)
            if not valid_block_height(self.registration_block_height):
                LOG.error(
                    'Unable to get distribution: invalid registration_block_height: %s'
                    % self.registration_block_height)
                raise Exception(
                    'Unable to get distribution: invalid registration_block_height: %s'
                    % self.registration_block_height)

            data = get_lrl(address=self.registration_address,
                           xpub=self.registration_xpub,
                           block_height=self.registration_block_height)
            if 'LRL' not in data:
                LOG.error('Unable to get distribution: invalid LRL data: %s' %
                          data)
                raise Exception('Unable to get distribution: invalid LRL: %s' %
                                data)
            distribution = {
                recipient[0]: recipient[1]
                for recipient in data['LRL']
            }

        elif transaction_type == 'Send2LSL':
            if not valid_address(self.registration_address):
                LOG.error(
                    'Unable to get distribution: invalid registration_address: %s'
                    % self.registration_address)
                raise Exception(
                    'Unable to get distribution: invalid registration_address: %s'
                    % self.registration_address)
            if not valid_xpub(self.registration_xpub):
                LOG.error(
                    'Unable to get distribution: invalid registration_xpub: %s'
                    % self.registration_xpub)
                raise Exception(
                    'Unable to get distribution: invalid registration_xpub: %s'
                    % self.registration_xpub)
            if not valid_block_height(self.registration_block_height):
                LOG.error(
                    'Unable to get distribution: invalid registration_block_height: %s'
                    % self.registration_block_height)
                raise Exception(
                    'Unable to get distribution: invalid registration_block_height: %s'
                    % self.registration_block_height)

            data = get_lsl(address=self.registration_address,
                           xpub=self.registration_xpub,
                           block_height=self.registration_block_height)
            if 'LSL' not in data:
                LOG.error('Unable to get distribution: invalid LSL data: %s' %
                          data)
                raise Exception('Unable to get distribution: invalid LSL: %s' %
                                data)
            distribution = {
                recipient[0]: recipient[1]
                for recipient in data['LSL']
            }

        elif transaction_type == 'Send2LAL':
            if not valid_address(self.sending_address):
                LOG.error(
                    'Unable to get distribution: invalid sending_address: %s' %
                    self.sending_address)
                raise Exception(
                    'Unable to get distribution: invalid sending_address: %s' %
                    self.sending_address)
            if not valid_xpub(self.registration_xpub):
                LOG.error(
                    'Unable to get distribution: invalid registration_xpub: %s'
                    % self.registration_xpub)
                raise Exception(
                    'Unable to get distribution: invalid registration_xpub: %s'
                    % self.registration_xpub)
            if not valid_block_height(self.registration_block_height):
                LOG.error(
                    'Unable to get distribution: invalid registration_block_height: %s'
                    % self.registration_block_height)
                raise Exception(
                    'Unable to get distribution: invalid registration_block_height: %s'
                    % self.registration_block_height)

            # The registration address of a LAL must always be the sending address
            data = get_lal(address=self.sending_address,
                           xpub=self.registration_xpub,
                           block_height=self.registration_block_height)
            if 'LAL' not in data:
                LOG.error('Unable to get distribution: invalid LAL data: %s' %
                          data)
                raise Exception('Unable to get distribution: invalid LAL: %s' %
                                data)

            LOG.info('LAL: %s' % data['LAL'])
            distribution = {}
            for utxo in self.unspent_outputs:
                prime_input_address_data = prime_input_address(
                    utxo.output_hash)
                prime_input_address_of_utxo = prime_input_address_data[
                    'prime_input_address'] if 'prime_input_address' in prime_input_address_data else None
                LOG.info('Prime input address of %s is %s' %
                         (utxo.output_hash, prime_input_address_of_utxo))

                linked_address = [
                    linked_address
                    for input_address, linked_address in data['LAL']
                    if input_address == prime_input_address_of_utxo
                ]
                # There should be exactly 1 linked address
                if len(linked_address) == 1:
                    distribution[linked_address[0]] = utxo.value
                else:
                    LOG.error(
                        'Something went wrong with the LAL: found %s linked addresses, should be exactly 1!'
                        % len(linked_address))
                    raise Exception(
                        'Something went wrong with the LAL: found %s linked addresses, should be exactly 1!'
                        % len(linked_address))

        else:
            raise NotImplementedError('Unknown transaction type %s' %
                                      transaction_type)

        LOG.info('distribution: %s' % distribution)
        return distribution
Example #5
0
 def test_valid_xpub_testnet(self, xpub, expected, description):
     helpers.configurationhelpers.get_use_testnet = mock.MagicMock(return_value=True)
     print(description)
     assert validators.valid_xpub(xpub) == expected, description