Example #1
0
def classic_address_to_xaddress(classic_address: str, tag: Optional[int],
                                is_test_network: bool) -> str:
    """
    Returns the X-Address representation of the data.

    Args:
        classic_address: The base58 encoding of the classic address.
        tag: The destination tag.
        is_test_network: Whether it is the test network or the main network.

    Returns:
        The X-Address representation of the data.

    Raises:
        XRPLAddressCodecException: If the classic address does not have enough bytes
            or the tag is invalid.
    """
    classic_address_bytes = decode_classic_address(classic_address)
    if len(classic_address_bytes) != 20:
        raise XRPLAddressCodecException("Account ID must be 20 bytes")

    if tag is not None and tag > MAX_32_BIT_UNSIGNED_INT:
        raise XRPLAddressCodecException("Invalid tag")

    flag = tag is not None
    if tag is None:
        tag = 0

    bytestring = PREFIX_BYTES_TEST if is_test_network else PREFIX_BYTES_MAIN
    bytestring += classic_address_bytes
    encoded_tag = bytes([
        flag,
        tag & 0xFF,
        tag >> 8 & 0xFF,
        tag >> 16 & 0xFF,
        tag >> 24 & 0xFF,
        0,
        0,
        0,
        0,
    ])
    bytestring += encoded_tag

    return base58.b58encode_check(bytestring,
                                  alphabet=XRPL_ALPHABET).decode("utf-8")
Example #2
0
def _decode(b58_string: str, prefix: bytes) -> bytes:
    """
    b58_string: A base58 value
    prefix: The prefix prepended to the bytestring

    Returns the byte decoding of the base58-encoded string.
    """
    prefix_length = len(prefix)
    decoded = base58.b58decode_check(b58_string, alphabet=XRPL_ALPHABET)
    if decoded[:prefix_length] != prefix:
        raise XRPLAddressCodecException("Provided prefix is incorrect")
    return decoded[prefix_length:]
Example #3
0
def _get_tag_from_buffer(buffer: bytes) -> Optional[int]:
    """
    Returns the destination tag extracted from the suffix of the X-Address.

    Args:
        buffer: The buffer to extract a destination tag from.

    Returns:
        The destination tag extracted from the suffix of the X-Address.
    """
    flag = buffer[0]
    if flag >= 2:
        raise XRPLAddressCodecException("Unsupported X-Address")
    if flag == 1:  # Little-endian to big-endian
        return (buffer[1] + buffer[2] * 0x100 + buffer[3] * 0x10000 +
                buffer[4] * 0x1000000)  # inverse of what happens in encode
    if flag != 0:
        raise XRPLAddressCodecException("Flag must be zero to indicate no tag")
    if bytes.fromhex("0000000000000000") != buffer[1:9]:
        raise XRPLAddressCodecException("Remaining bytes must be zero")
    return None
Example #4
0
def _encode(bytestring: bytes, prefix: List[int], expected_length: int) -> str:
    """
    Returns the base58 encoding of the bytestring, with the given data prefix
    (which indicates type) and while ensuring the bytestring is the expected
    length.
    """
    if expected_length and len(bytestring) != expected_length:
        error_message = """unexpected_payload_length: len(bytestring) does not match expected_length.
        Ensure that the bytes are a bytestring."""
        raise XRPLAddressCodecException(error_message)
    encoded_prefix = bytes(prefix)
    payload = encoded_prefix + bytestring
    return base58.b58encode_check(payload, alphabet=XRPL_ALPHABET).decode("utf-8")
Example #5
0
def encode_seed(entropy: bytes, encoding_type: CryptoAlgorithm) -> str:
    """
    Returns an encoded seed.

    Args:
        entropy: Entropy bytes of SEED_LENGTH.
        encoding_type: Either ED25519 or SECP256K1.

    Returns:
        An encoded seed.

    Raises:
        XRPLAddressCodecException: If entropy is not of length SEED_LENGTH
            or the encoding type is not one of CryptoAlgorithm.
    """
    if len(entropy) != SEED_LENGTH:
        raise XRPLAddressCodecException(f"Entropy must have length {SEED_LENGTH}")
    if encoding_type not in CryptoAlgorithm:
        raise XRPLAddressCodecException(
            f"Encoding type must be one of {CryptoAlgorithm}"
        )

    prefix = _ALGORITHM_TO_PREFIX_MAP[encoding_type]
    return _encode(entropy, prefix, SEED_LENGTH)
Example #6
0
def _is_test_address(prefix: bytes) -> bool:
    """
    Returns whether a decoded X-Address is a test address.

    Args:
        prefix: The first 2 bytes of an X-Address.

    Returns:
        Whether a decoded X-Address is a test address.

    Raises:
        XRPLAddressCodecException: If the prefix is invalid.
    """
    if PREFIX_BYTES_MAIN == prefix:
        return False
    if PREFIX_BYTES_TEST == prefix:
        return True
    raise XRPLAddressCodecException("Invalid X-Address: bad prefix")
Example #7
0
def decode_seed(seed: str) -> Tuple[bytes, CryptoAlgorithm]:
    """
    Returns (decoded seed, its algorithm).

    Args:
        seed: b58 encoding of a seed.

    Returns:
        (decoded seed, its algorithm).

    Raises:
        XRPLAddressCodecException: If the seed is invalid.
    """
    for algorithm in CryptoAlgorithm:
        prefix = _ALGORITHM_TO_PREFIX_MAP[algorithm]
        try:
            decoded_result = _decode(seed, bytes(prefix))
            return decoded_result, algorithm
        except XRPLAddressCodecException:
            # prefix is incorrect, wrong algorithm
            continue
    raise XRPLAddressCodecException(
        "Invalid seed; could not determine encoding algorithm")