Ejemplo n.º 1
0
def valid_xpub(xpub):
    from helpers.configurationhelpers import get_use_testnet
    testnet = get_use_testnet()
    if testnet is True:
        return isinstance(xpub, str) and xpub[:4] == "tpub"
    else:
        return isinstance(xpub, str) and xpub[:4] == "xpub"
    def test_verify_message_with_testnet_address(self):
        if get_use_testnet() is False:
            print('Change configuration to use testnet to test this!!')
            return

        address = 'n2xqSGhqeQqiC6rp34NmPF8xmjQrcxLc6K'
        message = 'This is a test message for verification of n2xq'
        signature = 'H4NTp6Z3RWVndpmapw3sJ/CZd0jDS0evgQxasAN+hn3KGhoMLNvzs1Ms3nvPAqdf04XG3O6A4QmmIi70y14Lh18='
        assert verify_message(address=address, message=message, signature=signature)
Ejemplo n.º 3
0
def valid_address(address):
    if not isinstance(address, str):
        return False

    from helpers.configurationhelpers import get_use_testnet
    testnet = get_use_testnet()
    if testnet is True:
        return re.match(TESTNET_ADDRESS_REGEX,
                        address) is not None or valid_bech32_address(address)
    else:
        return re.match(MAINNET_ADDRESS_REGEX,
                        address) is not None or valid_bech32_address(address)
Ejemplo n.º 4
0
def add_key():
    wallet = load_wallet()

    try:
        address = privkey_to_address(
            args.private_key,
            magicbyte=0 if get_use_testnet() is False else 111)
    except AssertionError:
        print('Invalid private key: %s' % args.private_key, file=sys.stderr)
        sys.exit(1)

    new_key = {address: args.private_key}
    wallet.update(new_key)

    save_wallet(wallet)
Ejemplo n.º 5
0
def get_recommended_fee_blockcypher():
    url = 'https://api.blockcypher.com/v1/btc/test3' if get_use_testnet(
    ) is True else 'https://api.blockcypher.com/v1/btc/main'

    try:
        LOG.info('GET %s' % url)
        r = requests.get(url=url)
        data = r.json()
    except Exception as ex:
        raise Exception('Unable get recommended fee from blockcypher.com: %s' %
                        ex)

    return {
        'high_priority': data['high_fee_per_kb'],
        'low_priority': data['low_fee_per_kb'],
        'medium_priority': data['medium_fee_per_kb']
    }
Ejemplo n.º 6
0
def valid_bech32_address(address):
    if not isinstance(address, str):
        return False

    hrp, data = bech32_decode(address)
    if (hrp, data) == (None, None):
        return False

    from helpers.configurationhelpers import get_use_testnet
    testnet = get_use_testnet()
    if testnet is True:
        return re.match(LOWERCASE_TESTNET_BECH32_ADDRESS_REGEX,
                        address) is not None or re.match(
                            UPPERCASE_TESTNET_BECH32_ADDRESS_REGEX,
                            address) is not None
    else:
        return re.match(LOWERCASE_MAINNET_BECH32_ADDRESS_REGEX,
                        address) is not None or re.match(
                            UPPERCASE_MAINNET_BECH32_ADDRESS_REGEX,
                            address) is not None
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import bitcoin
from bitcoin.wallet import CBitcoinSecret
from bitcoin.signmessage import BitcoinMessage, VerifyMessage, SignMessage

from helpers.configurationhelpers import get_use_testnet
bitcoin.SelectParams(
    name='testnet' if get_use_testnet() is True else 'mainnet')


def sign_message(message, private_key):
    key = CBitcoinSecret(private_key)
    return SignMessage(key=key, message=BitcoinMessage(message)).decode()


def verify_message(address, message, signature):
    try:
        return VerifyMessage(address=address,
                             message=BitcoinMessage(message),
                             sig=signature)
    except Exception as ex:
        return False


def sign_and_verify(private_key, message, address):
    key = CBitcoinSecret(private_key)
    signature = SignMessage(key=key, message=BitcoinMessage(message))
    assert VerifyMessage(address=address,
                         message=BitcoinMessage(message),
Ejemplo n.º 8
0
    def run(self):
        LOG.info('Running Spellbook Script: %s' %
                 os.path.splitext(os.path.basename(__file__))[0])

        if self.json is not None:
            if 'seller_id' not in self.json:
                LOG.error(
                    'Payment request json does not contain the seller id')
                return

            if 'amount_fiat' not in self.json:
                LOG.error(
                    'Payment request json does not contain the fiat amount!')
                return

            if 'currency' not in self.json:
                LOG.error(
                    'Payment request json does not contain the fiat currency!')
                return
            elif self.json['currency'] not in ['EUR', 'USD']:
                LOG.error(
                    'Payment processor currently only supports EUR or USD as currency!'
                )
                return

            # Create a new payment request
            payment_request = PaymentRequest()
            payment_request.seller_id = self.json['seller_id']
            payment_request.amount_fiat = self.json['amount_fiat']
            payment_request.currency = self.json['currency']
            payment_request.note = self.json[
                'note'] if 'note' in self.json else None

            # Use the number of times the trigger has been triggered as the index in the hot wallet account
            payment_request.address = get_address_from_wallet(
                account=ACCOUNT, index=self.triggered)

            # Get the current BTC price from bitcoinaverage
            url = 'https://apiv2.bitcoinaverage.com/indices/global/ticker/BTC{currency}'.format(
                currency=payment_request.currency)
            LOG.info('Retrieving BTC%s price from bitcoinaverage.com' %
                     payment_request.currency)
            LOG.info('GET %s' % url)
            try:
                r = requests.get(url=url)
                price_data = r.json()
            except Exception as ex:
                LOG.error(
                    'Unable to retrieve BTC price from bitcoinaverage.com: %s'
                    % ex)
                self.http_response = {
                    'error':
                    'Unable to convert %s amount to BTC amount' %
                    payment_request.currency
                }
                return

            payment_request.price_btc = price_data['last']
            payment_request.price_timestamp = price_data['timestamp']

            if payment_request.price_btc == 0:
                LOG.error('BTC price can not be 0!')
                self.http_response = {
                    'error':
                    'Unable to convert %s amount to BTC amount' %
                    payment_request.currency
                }
                return

            payment_request.amount_btc = int(payment_request.amount_fiat /
                                             payment_request.price_btc * 1e8)

            LOG.info('Created new payment request: %s' %
                     payment_request.payment_request_id)
            LOG.info('Fiat Amount: %s %s' %
                     (payment_request.amount_fiat, payment_request.currency))
            LOG.info('BTC Amount: %s (price %s %s/BTC @ %s)' %
                     (payment_request.amount_btc, payment_request.price_btc,
                      payment_request.currency,
                      datetime.fromtimestamp(payment_request.price_timestamp
                                             ).strftime('%Y-%m-%d %H:%M:%S')))
            LOG.info('Note: %s' % payment_request.note)
            LOG.info('Address: %s' % payment_request.address)

            payment_request.save()

            # Set the HTTP response with the payment request details
            self.http_response = payment_request.json_encodable()

            # Create a trigger to monitor the balance of the address (This is a fallback in case the listener doesn't pick up the transaction)
            # The script will then check the number of confirmations of the transaction if one is received
            trigger = get_trigger(
                trigger_id=payment_request.payment_request_id,
                trigger_type=TriggerType.BALANCE)
            trigger.address = payment_request.address
            trigger.amount = payment_request.amount_btc

            trigger.script = os.path.join('PaymentProcessor',
                                          'PaymentProcessorPaymentStatus.py')
            trigger.data = {
                'payment_request_id': payment_request.payment_request_id
            }
            trigger.self_destruct = int(time.time()) + REQUEST_TIMEOUT
            trigger.status = 'Active'
            trigger.multi = True
            trigger.save()

            # Spawn up a separate process to listen for the payment transaction
            url = 'http://%s:%s/spellbook/triggers/PaymentProcessorTransactionReceived/post' % (
                get_host(), get_port())
            notify_program = os.path.join('helpers', 'notify_transaction.py')
            command = r'%s %s %s #txid#' % (notify_program, url,
                                            payment_request.payment_request_id)

            # Construct the command for the listener so that it listens for any receiving transactions on the address and executes the notify_transaction program when
            # a transaction is detected and stop the listener if no tx happens within the timeout period.
            listener_program = os.path.join('listeners',
                                            'transaction_listener.py')
            run_command = r'%s --address=%s --timeout=%s --exit --receive --command="%s"' % (
                listener_program, payment_request.address, LISTENER_TIMEOUT,
                command)

            # If we are configured for testnet we must also add the --testnet flag to the listener
            if get_use_testnet():
                run_command += ' --testnet'

            action = get_action(action_id='start_listener',
                                action_type=ActionType.SPAWNPROCESS)
            action.run_command = run_command

            # Run the action immediately instead of saving it, so we are not creating new actions with each request
            action.run()
Ejemplo n.º 9
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from binascii import hexlify, unhexlify

from .BIP32 import bip32_ckd, bip32_extract_key, MAGICBYTE, bip32_master_key, VERSION_BYTES, bip32_privtopub
from .BIP39 import get_seed
from helpers.publickeyhelpers import encode_pubkey, pubkey_to_address
from helpers.privatekeyhelpers import encode_privkey, privkey_to_address
from helpers.configurationhelpers import get_use_testnet

HARDENED = 2**31
COIN_TYPE = 1 if get_use_testnet() is True else 0


def get_address_from_xpub(xpub, i):
    """
    Get a Bitcoin address from an xpub key

    :param xpub: The xpub key
    :param i: The index of the address
    :return: A Bitcoin Address
    """
    pub0 = bip32_ckd(xpub, 0)
    public_key = bip32_ckd(pub0, i)
    hex_key = encode_pubkey(bip32_extract_key(public_key), 'hex_compressed')
    address = pubkey_to_address(hex_key, magicbyte=MAGICBYTE)

    return address


def get_addresses_from_xpub(xpub, i=100):
Ejemplo n.º 10
0
from helpers.privatekeyhelpers import privkey_to_pubkey, add_privkeys
from helpers.publickeyhelpers import add_pubkeys, compress, bin_hash160, encode_pubkey, pubkey_to_address

from helpers.configurationhelpers import get_use_testnet

BIP32_DERIVATION_PATH_REGEX = "^m(\/\d+'?)*"
HARDENED = 2**31

MAINNET_PRIVATE = b'\x04\x88\xAD\xE4'
MAINNET_PUBLIC = b'\x04\x88\xB2\x1E'
TESTNET_PRIVATE = b'\x04\x35\x83\x94'
TESTNET_PUBLIC = b'\x04\x35\x87\xCF'
PRIVATE = [MAINNET_PRIVATE, TESTNET_PRIVATE]
PUBLIC = [MAINNET_PUBLIC, TESTNET_PUBLIC]

VERSION_BYTES = TESTNET_PRIVATE if get_use_testnet(
) is True else MAINNET_PRIVATE
MAGICBYTE = 111 if get_use_testnet() is True else 0


def set_chain_mode(mainnet=True):
    """
    Override the configuration to switch between mainnet and testnet mode

    :param mainnet: True or False
    """
    global VERSION_BYTES, MAGICBYTE
    VERSION_BYTES = MAINNET_PRIVATE if mainnet is True else TESTNET_PRIVATE
    MAGICBYTE = 0 if mainnet is True else 111


# Set the chain mode based on the current configuration
Ejemplo n.º 11
0
def teardown_module(module):
    """ teardown any state that was previously setup with a setup_module
    method."""
    set_chain_mode(mainnet=(get_use_testnet() is False))