Decode base58check encoded input to original raw bytes.

    :param bytes val: The value to base58cheeck decode.
    :param bytes charset: (optional) The character set to use for decoding.
    :return: the decoded bytes.
    :rtype: bytes

    Usage::

      >>> import base58check
      >>> base58check.b58decode('\x00v\x80\xad\xec\x8e\xab\xca\xba\xc6v\xbe'
      ...                       '\x9e\x83\x85J\xde\x0b\xd2,\xdb\x0b\xb9`\xde')
      b'1BoatSLRHtKNngkdXEeobR76b53LETtpyT'

def b58decode(val, charset=DEFAULT_CHARSET):
    """Decode base58check encoded input to original raw bytes.

    :param bytes val: The value to base58cheeck decode.
    :param bytes charset: (optional) The character set to use for decoding.
    :return: the decoded bytes.
    :rtype: bytes

    Usage::

      >>> import base58check
      >>> base58check.b58decode('\x00v\x80\xad\xec\x8e\xab\xca\xba\xc6v\xbe'
      ...                       '\x9e\x83\x85J\xde\x0b\xd2,\xdb\x0b\xb9`\xde')
      b'1BoatSLRHtKNngkdXEeobR76b53LETtpyT'
    """

    def _b58decode_int(val):
        output = 0
        for char in val:
            output = output * base + charset.index(char)
        return output

    if isinstance(val, str):
        val = val.encode()

    if isinstance(charset, str):
        charset = charset.encode()

    base = len(charset)

    if not base == 58:
        raise ValueError('charset base must be 58, not %s' % base)

    pad_len = len(val)
    val = val.lstrip(bytes([charset[0]]))
    pad_len -= len(val)

    acc = _b58decode_int(val)

    result = deque()
    while acc > 0:
        acc, mod = divmod(acc, 256)
        result.appendleft(mod)

    prefix = b'\0' * pad_len
    return prefix + bytes(result)