Skip to content

swap_handle_check_address()

ledger-secure-sdk/lib_standard_app/swap_entrypoints.h

/* This handle is called when the Exchange application wants to ensure that a
 * given address belongs to the device.
 *
 * If the address does belong to the device, result is set to 1. Otherwise it
 * is set to 0.
 */
void swap_handle_check_address(check_address_parameters_t *params);

ledger-secure-sdk/lib_standard_app/swap_lib_calls.h

typedef struct check_address_parameters_s {
    // INPUTS //
    // Additional data when dealing with tokens
    // Content is coin application specific
    uint8_t *coin_configuration;
    uint8_t  coin_configuration_length;

    // serialized path, segwit, version prefix, hash used, dictionary etc.
    // fields and serialization format are coin application specific
    uint8_t *address_parameters;
    uint8_t  address_parameters_length;

    // The address to check
    char *address_to_check;

    // Extra content that may be relevant depending on context: memo, calldata, ...
    // Content is coin application specific
    char *extra_id_to_check;

    // OUTPUT //
    // Set to 1 if the address belongs to the device. 0 otherwise.
    int result;
} check_address_parameters_t;


Example of handle implementation in Solana

app-solana/src/swap/handle_check_address.c

#include <string.h>

#include "handle_check_address.h"
#include "os.h"
#include "utils.h"
#include "sol/printer.h"

// Helper to get our public key in base58 format for a given derivation path
static int derive_public_key(const uint8_t *buffer,
                             uint16_t buffer_length,
                             uint8_t public_key[PUBKEY_LENGTH],
                             char public_key_str[BASE58_PUBKEY_LENGTH]) {
    uint32_t derivation_path[MAX_BIP32_PATH_LENGTH];
    uint32_t path_length;
    int ret;

    ret = read_derivation_path(buffer, buffer_length, derivation_path, &path_length) != 0;
    if (ret != 0) {
        return ret;
    }

    get_public_key(public_key, derivation_path, path_length);

    return encode_base58(public_key, PUBKEY_LENGTH, public_key_str, BASE58_PUBKEY_LENGTH);
}

// Check that params->address_to_check belongs to us on derivation path params->address_parameters
void swap_handle_check_address(check_address_parameters_t *params) {
    PRINTF("Inside Solana swap_handle_check_address\n");
    // ensure result is zero even if an exception is thrown
    params->result = 0;
    PRINTF("Params on the address %d\n", (unsigned int) params);

    if (params->address_parameters == NULL) {
        PRINTF("derivation path expected\n");
        return;
    }

    if (params->address_to_check == NULL) {
        PRINTF("Address to check expected\n");
        return;
    }
    PRINTF("Address to check %s\n", params->address_to_check);

    if (params->extra_id_to_check == NULL) {
        PRINTF("extra_id_to_check expected\n");
        return;
    } else if (params->extra_id_to_check[0] != '\0') {
        PRINTF("extra_id_to_check expected empty, not '%s'\n", params->extra_id_to_check);
        return;
    }

    uint8_t public_key[PUBKEY_LENGTH];
    char public_key_str[BASE58_PUBKEY_LENGTH];
    if (derive_public_key(params->address_parameters,
                          params->address_parameters_length,
                          public_key,
                          public_key_str) != 0) {
        PRINTF("Failed to derive public key\n");
        return;
    }
    // Only public_key_str is useful in this context
    UNUSED(public_key);

    if (strcmp(params->address_to_check, public_key_str) != 0) {
        PRINTF("Address %s != %s\n", params->address_to_check, public_key_str);
        return;
    }

    PRINTF("Addresses match\n");
    params->result = 1;
}