Ejemplo n.º 1
0
def make_fully_valid(pubkey_start):
    """Take a too short data pubkey and make it look like a real pubkey.

    Take an obfuscated chunk of data that is two bytes too short to be a pubkey and
    add a sign byte to its beginning and a nonce byte to its end. Choose these
    bytes so that the resulting sequence of bytes is a fully valid pubkey (i.e. on
    the ECDSA curve). Find the correct bytes by guessing randomly until the check
    passes. (In parsing, these two bytes are ignored.)
    """
    assert type(pubkey_start) == bytes
    assert len(
        pubkey_start
    ) == 31  # One sign byte and one nonce byte required (for 33 bytes).

    random_bytes = hashlib.sha256(
        pubkey_start).digest()  # Deterministically generated, for unit tests.
    sign = (random_bytes[0] & 0b1) + 2  # 0x02 or 0x03
    nonce = initial_nonce = random_bytes[1]

    pubkey = b''
    while not script.is_fully_valid(pubkey):
        # Increment nonce.
        nonce += 1
        assert nonce != initial_nonce

        # Construct a possibly fully valid public key.
        pubkey = bytes([sign]) + pubkey_start + bytes([nonce % 256])

    assert len(pubkey) == 33
    return pubkey
Ejemplo n.º 2
0
def make_fully_valid(pubkey_start):
    """Take a too short data pubkey and make it look like a real pubkey.

    Take an obfuscated chunk of data that is two bytes too short to be a pubkey and
    add a sign byte to its beginning and a nonce byte to its end. Choose these
    bytes so that the resulting sequence of bytes is a fully valid pubkey (i.e. on
    the ECDSA curve). Find the correct bytes by guessing randomly until the check
    passes. (In parsing, these two bytes are ignored.)
    """
    assert type(pubkey_start) == bytes
    assert len(pubkey_start) == 31    # One sign byte and one nonce byte required (for 33 bytes).

    random_bytes = hashlib.sha256(pubkey_start).digest()      # Deterministically generated, for unit tests.
    sign = (random_bytes[0] & 0b1) + 2                  # 0x02 or 0x03
    nonce = initial_nonce = random_bytes[1]

    pubkey = b''
    while not script.is_fully_valid(pubkey):
        # Increment nonce.
        nonce += 1
        assert nonce != initial_nonce

        # Construct a possibly fully valid public key.
        pubkey = bytes([sign]) + pubkey_start + bytes([nonce % 256])

    assert len(pubkey) == 33
    return pubkey
Ejemplo n.º 3
0
def compose_transaction(db,
                        name,
                        params,
                        encoding='auto',
                        fee_per_kb=config.DEFAULT_FEE_PER_KB,
                        regular_dust_size=config.DEFAULT_REGULAR_DUST_SIZE,
                        multisig_dust_size=config.DEFAULT_MULTISIG_DUST_SIZE,
                        op_return_value=config.DEFAULT_OP_RETURN_VALUE,
                        pubkey=None,
                        allow_unconfirmed_inputs=False,
                        fee=None,
                        fee_provided=0):
    """Create and return a transaction."""

    # Get provided pubkeys.
    if type(pubkey) == str:
        provided_pubkeys = [pubkey]
    elif type(pubkey) == list:
        provided_pubkeys = pubkey
    elif pubkey == None:
        provided_pubkeys = []
    else:
        assert False

    # Get additional pubkeys from `source` and `destination` params.
    # Convert `source` and `destination` to pubkeyhash form.
    for address_name in ['source', 'destination']:
        if address_name in params:
            address = params[address_name]
            provided_pubkeys += script.extract_pubkeys(address)
            params[address_name] = script.make_pubkeyhash(address)

    # Check validity of collected pubkeys.
    for pubkey in provided_pubkeys:
        if not script.is_fully_valid(binascii.unhexlify(pubkey)):
            raise script.AddressError('invalid public key: {}'.format(pubkey))

    compose_method = sys.modules['counterpartylib.lib.messages.{}'.format(
        name)].compose
    compose_params = inspect.getargspec(compose_method)[0]
    missing_params = [
        p for p in compose_params if p not in params and p != 'db'
    ]
    for param in missing_params:
        params[param] = None

    # try:  # NOTE: For debugging, e.g. with `Invalid Params` error.
    tx_info = compose_method(db, **params)
    return transaction.construct(
        db,
        tx_info,
        encoding=encoding,
        fee_per_kb=fee_per_kb,
        regular_dust_size=regular_dust_size,
        multisig_dust_size=multisig_dust_size,
        op_return_value=op_return_value,
        provided_pubkeys=provided_pubkeys,
        allow_unconfirmed_inputs=allow_unconfirmed_inputs,
        exact_fee=fee,
        fee_provided=fee_provided)
Ejemplo n.º 4
0
def compose_transaction(db, name, params,
                        encoding='auto',
                        fee_per_kb=config.DEFAULT_FEE_PER_KB,
                        estimate_fee_per_kb=None, estimate_fee_per_kb_nblocks=config.ESTIMATE_FEE_NBLOCKS,
                        regular_dust_size=config.DEFAULT_REGULAR_DUST_SIZE,
                        multisig_dust_size=config.DEFAULT_MULTISIG_DUST_SIZE,
                        op_return_value=config.DEFAULT_OP_RETURN_VALUE,
                        pubkey=None,
                        allow_unconfirmed_inputs=False,
                        fee=None,
                        fee_provided=0,
                        unspent_tx_hash=None, custom_inputs=None, dust_return_pubkey=None, disable_utxo_locks=False):
    """Create and return a transaction."""

    # Get provided pubkeys.
    if type(pubkey) == str:
        provided_pubkeys = [pubkey]
    elif type(pubkey) == list:
        provided_pubkeys = pubkey
    elif pubkey == None:
        provided_pubkeys = []
    else:
        assert False

    # Get additional pubkeys from `source` and `destination` params.
    # Convert `source` and `destination` to pubkeyhash form.
    for address_name in ['source', 'destination']:
        if address_name in params:
            address = params[address_name]
            provided_pubkeys += script.extract_pubkeys(address)
            params[address_name] = script.make_pubkeyhash(address)

    # Check validity of collected pubkeys.
    for pubkey in provided_pubkeys:
        if not script.is_fully_valid(binascii.unhexlify(pubkey)):
            raise script.AddressError('invalid public key: {}'.format(pubkey))

    compose_method = sys.modules['counterpartylib.lib.messages.{}'.format(name)].compose
    compose_params = inspect.getargspec(compose_method)[0]
    missing_params = [p for p in compose_params if p not in params and p != 'db']
    for param in missing_params:
        params[param] = None

    tx_info = compose_method(db, **params)
    return transaction.construct(db, tx_info, encoding=encoding,
                                        fee_per_kb=fee_per_kb,
                                        estimate_fee_per_kb=estimate_fee_per_kb, estimate_fee_per_kb_nblocks=estimate_fee_per_kb_nblocks,
                                        regular_dust_size=regular_dust_size,
                                        multisig_dust_size=multisig_dust_size,
                                        op_return_value=op_return_value,
                                        provided_pubkeys=provided_pubkeys,
                                        allow_unconfirmed_inputs=allow_unconfirmed_inputs,
                                        exact_fee=fee,
                                        fee_provided=fee_provided,
                                        unspent_tx_hash=unspent_tx_hash, custom_inputs=custom_inputs,
                                        dust_return_pubkey=dust_return_pubkey,
                                        disable_utxo_locks=disable_utxo_locks)
Ejemplo n.º 5
0
def get_pubkey_monosig(pubkeyhash, pubkey_resolver=input_pubkey):
    if wallet.is_valid(pubkeyhash):

        # If in wallet, get from wallet.
        logging.debug('Looking for public key for `{}` in wallet.'.format(pubkeyhash))
        if wallet.is_mine(pubkeyhash):
            pubkey = wallet.get_pubkey(pubkeyhash)
            if pubkey:
                return pubkey
        logging.debug('Public key for `{}` not found in wallet.'.format(pubkeyhash))

        # If in blockchain (and not in wallet), get from blockchain.
        logging.debug('Looking for public key for `{}` in blockchain.'.format(pubkeyhash))
        try:
            pubkey = util.api('search_pubkey', {'pubkeyhash': pubkeyhash, 'provided_pubkeys': None})
        except util.RPCError as e:
            pubkey = None
        if pubkey:
            return pubkey
        logging.debug('Public key for `{}` not found in blockchain.'.format(pubkeyhash))

        # If not in wallet and not in blockchain, get from user.
        answer = pubkey_resolver(pubkeyhash)
        if not answer:
            return None

        # Public Key or Private Key?
        is_fully_valid_pubkey = True
        try:
            is_fully_valid_pubkey = script.is_fully_valid(binascii.unhexlify(answer))
        except binascii.Error:
            is_fully_valid_pubkey = False
        if is_fully_valid_pubkey:
            logging.debug('Answer was a fully valid public key.')
            pubkey = answer
        else:
            logging.debug('Answer was not a fully valid public key. Assuming answer was a private key.')
            private_key = answer
            try:
                pubkey = script.private_key_to_public_key(private_key)
            except script.AltcoinSupportError:
                raise InputError('invalid private key')
        if pubkeyhash != script.pubkey_to_pubkeyhash(binascii.unhexlify(bytes(pubkey, 'utf-8'))):
            raise InputError('provided public or private key does not match the source address')

        return pubkey

    return None
Ejemplo n.º 6
0
def get_pubkey_monosig(pubkeyhash, pubkey_resolver=input_pubkey):
    if wallet.is_valid(pubkeyhash):

        # If in wallet, get from wallet.
        logging.debug("Looking for public key for `{}` in wallet.".format(pubkeyhash))
        if wallet.is_mine(pubkeyhash):
            pubkey = wallet.get_pubkey(pubkeyhash)
            if pubkey:
                return pubkey
        logging.debug("Public key for `{}` not found in wallet.".format(pubkeyhash))

        # If in blockchain (and not in wallet), get from blockchain.
        logging.debug("Looking for public key for `{}` in blockchain.".format(pubkeyhash))
        try:
            pubkey = util.api("search_pubkey", {"pubkeyhash": pubkeyhash, "provided_pubkeys": None})
        except util.RPCError as e:
            pubkey = None
        if pubkey:
            return pubkey
        logging.debug("Public key for `{}` not found in blockchain.".format(pubkeyhash))

        # If not in wallet and not in blockchain, get from user.
        answer = pubkey_resolver(pubkeyhash)
        if not answer:
            return None

        # Public Key or Private Key?
        is_fully_valid_pubkey = True
        try:
            is_fully_valid_pubkey = script.is_fully_valid(binascii.unhexlify(answer))
        except binascii.Error:
            is_fully_valid_pubkey = False
        if is_fully_valid_pubkey:
            logging.debug("Answer was a fully valid public key.")
            pubkey = answer
        else:
            logging.debug("Answer was not a fully valid public key. Assuming answer was a private key.")
            private_key = answer
            try:
                pubkey = script.private_key_to_public_key(private_key)
            except script.AltcoinSupportError:
                raise InputError("invalid private key")
        if pubkeyhash != script.pubkey_to_pubkeyhash(binascii.unhexlify(bytes(pubkey, "utf-8"))):
            raise InputError("provided public or private key does not match the source address")

        return pubkey

    return None
Ejemplo n.º 7
0
def make_fully_valid(pubkey_start):
    assert type(pubkey_start) == bytes
    assert len(
        pubkey_start
    ) == 31  # One sign byte and one nonce byte required (for 33 bytes).

    random_bytes = hashlib.sha256(
        pubkey_start).digest()  # Deterministically generated, for unit tests.
    sign = (random_bytes[0] & 0b1) + 2  # 0x02 or 0x03
    nonce = initial_nonce = random_bytes[1]

    pubkey = b''
    while not script.is_fully_valid(pubkey):
        # Increment nonce.
        nonce += 1
        assert nonce != initial_nonce

        # Construct a possibly fully valid public key.
        pubkey = bytes([sign]) + pubkey_start + bytes([nonce % 256])

    assert len(pubkey) == 33
    return pubkey
Ejemplo n.º 8
0
def compose_transaction(
        db,
        name,
        params,
        encoding='auto',
        fee_per_kb=None,
        estimate_fee_per_kb=None,
        estimate_fee_per_kb_conf_target=config.ESTIMATE_FEE_CONF_TARGET,
        estimate_fee_per_kb_mode=config.ESTIMATE_FEE_MODE,
        regular_dust_size=config.DEFAULT_REGULAR_DUST_SIZE,
        multisig_dust_size=config.DEFAULT_MULTISIG_DUST_SIZE,
        op_return_value=config.DEFAULT_OP_RETURN_VALUE,
        pubkey=None,
        allow_unconfirmed_inputs=False,
        fee=None,
        fee_provided=0,
        unspent_tx_hash=None,
        custom_inputs=None,
        dust_return_pubkey=None,
        disable_utxo_locks=False,
        extended_tx_info=False,
        p2sh_source_multisig_pubkeys=None,
        p2sh_source_multisig_pubkeys_required=None,
        p2sh_pretx_txid=None,
        old_style_api=True,
        segwit=False):
    """Create and return a transaction."""

    # Get provided pubkeys.
    if type(pubkey) == str:
        provided_pubkeys = [pubkey]
    elif type(pubkey) == list:
        provided_pubkeys = pubkey
    elif pubkey == None:
        provided_pubkeys = []
    else:
        assert False

    # Get additional pubkeys from `source` and `destination` params.
    # Convert `source` and `destination` to pubkeyhash form.
    for address_name in ['source', 'destination']:
        if address_name in params:
            address = params[address_name]
            if isinstance(address, list):
                """pubkey_list = []
                for iaddr in address:
                    provided_pubkeys += script.extract_pubkeys(iaddr)
                    pubkey_list.append(script.make_pubkeyhash(iaddr))
                params[address_name] = pubkey_list"""
            else:
                provided_pubkeys += script.extract_pubkeys(address)
                params[address_name] = script.make_pubkeyhash(address)

    # Check validity of collected pubkeys.
    for pubkey in provided_pubkeys:
        if not script.is_fully_valid(binascii.unhexlify(pubkey)):
            raise script.AddressError('invalid public key: {}'.format(pubkey))

    compose_method = sys.modules['counterpartylib.lib.messages.{}'.format(
        name)].compose
    compose_params = inspect.getargspec(compose_method)[0]
    missing_params = [
        p for p in compose_params if p not in params and p != 'db'
    ]
    for param in missing_params:
        params[param] = None

    # dont override fee_per_kb if specified
    if fee_per_kb is not None:
        estimate_fee_per_kb = False
    else:
        fee_per_kb = config.DEFAULT_FEE_PER_KB

    if 'extended_tx_info' in params:
        extended_tx_info = params['extended_tx_info']
        del params['extended_tx_info']

    if 'old_style_api' in params:
        old_style_api = params['old_style_api']
        del params['old_style_api']

    if 'segwit' in params:
        segwit = params['segwit']
        del params['segwit']

    tx_info = compose_method(db, **params)
    return transaction.construct(
        db,
        tx_info,
        encoding=encoding,
        fee_per_kb=fee_per_kb,
        estimate_fee_per_kb=estimate_fee_per_kb,
        estimate_fee_per_kb_conf_target=estimate_fee_per_kb_conf_target,
        regular_dust_size=regular_dust_size,
        multisig_dust_size=multisig_dust_size,
        op_return_value=op_return_value,
        provided_pubkeys=provided_pubkeys,
        allow_unconfirmed_inputs=allow_unconfirmed_inputs,
        exact_fee=fee,
        fee_provided=fee_provided,
        unspent_tx_hash=unspent_tx_hash,
        custom_inputs=custom_inputs,
        dust_return_pubkey=dust_return_pubkey,
        disable_utxo_locks=disable_utxo_locks,
        extended_tx_info=extended_tx_info,
        p2sh_source_multisig_pubkeys=p2sh_source_multisig_pubkeys,
        p2sh_source_multisig_pubkeys_required=
        p2sh_source_multisig_pubkeys_required,
        p2sh_pretx_txid=p2sh_pretx_txid,
        old_style_api=old_style_api,
        segwit=segwit)