diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 98b720fe..f2fb620f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -4,5 +4,5 @@ - [ ] Target branch is `develop` - [ ] Application version has been bumped - diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index bc8fe835..690a61dc 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -8,54 +8,37 @@ on: pull_request: jobs: - build: - name: SonarQube analyze + sonarcloud: runs-on: ubuntu-latest container: image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-legacy:latest + env: - SONAR_SCANNER_VERSION: 4.7.0.2747 - SONAR_SERVER_URL: "https://sonarcloud.io" BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - name: Set up JDK 11 - uses: actions/setup-java@v1 - with: - java-version: 11 - - name: Download and set up sonar-scanner - env: - SONAR_SCANNER_DOWNLOAD_URL: https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${{ env.SONAR_SCANNER_VERSION }}-linux.zip - run: | - apt-get update -y - apt-get upgrade -y - DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata - curl -sL https://deb.nodesource.com/setup_16.x | bash - - apt-get install -y gcovr nodejs unzip lcov - mkdir -p $HOME/.sonar - curl -sSLo $HOME/.sonar/sonar-scanner.zip ${{ env.SONAR_SCANNER_DOWNLOAD_URL }} - unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/ - echo "$HOME/.sonar/sonar-scanner-${{ env.SONAR_SCANNER_VERSION }}-linux/bin" >> $GITHUB_PATH - - name: Download and set up build-wrapper - env: - BUILD_WRAPPER_DOWNLOAD_URL: ${{ env.SONAR_SERVER_URL }}/static/cpp/build-wrapper-linux-x86.zip - run: | - curl -sSLo $HOME/.sonar/build-wrapper-linux-x86.zip ${{ env.BUILD_WRAPPER_DOWNLOAD_URL }} - unzip -o $HOME/.sonar/build-wrapper-linux-x86.zip -d $HOME/.sonar/ - echo "$HOME/.sonar/build-wrapper-linux-x86" >> $GITHUB_PATH - - name: Generate code coverage - working-directory: libsol - run: | - make COVERAGE=1 - gcovr --root .. --sonarqube ../coverage.xml - - name: Run build-wrapper - run: | - build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make clean all - - name: Run sonar-scanner - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: | - sonar-scanner --define sonar.host.url="${{ env.SONAR_SERVER_URL }}" --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" + - uses: actions/checkout@v3 + with: + # Disabling shallow clone is recommended for improving relevancy of reporting + fetch-depth: 0 + - name: Install dependencies + run: | + apt-get update -y + apt-get upgrade -y + DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata + apt-get install -y libcmocka-dev gcovr unzip + - name: Install sonar-scanner and build-wrapper + uses: sonarsource/sonarcloud-github-c-cpp@v2 + + - name: Generate code coverage + working-directory: libsol + run: | + make COVERAGE=1 + gcovr --root .. --sonarqube ../coverage.xml + - name: Run build-wrapper + run: | + build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make clean all + - name: Run sonar-scanner + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: sonar-scanner --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" #Consult https://docs.sonarcloud.io/advanced-setup/ci-based-analysis/sonarscanner-cli/ for more information and options diff --git a/Makefile b/Makefile index 9a910bff..57080871 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ APP_LOAD_PARAMS += $(COMMON_LOAD_PARAMS) APPNAME = "Solana" APPVERSION_M = 1 APPVERSION_N = 4 -APPVERSION_P = 2 +APPVERSION_P = 3 APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)" ifeq ($(TARGET_NAME),TARGET_NANOS) @@ -131,6 +131,9 @@ include $(BOLOS_SDK)/Makefile.glyphs APP_SOURCE_PATH += src SDK_SOURCE_PATH += lib_stusb lib_stusb_impl +# Allow usage of function from lib_standard_app/crypto_helpers.c +APP_SOURCE_FILES += ${BOLOS_SDK}/lib_standard_app/crypto_helpers.c + ifneq ($(TARGET_NAME),TARGET_STAX) SDK_SOURCE_PATH += lib_ux endif diff --git a/libsol/common_byte_strings.h b/libsol/common_byte_strings.h index b38c675b..67e246c4 100644 --- a/libsol/common_byte_strings.h +++ b/libsol/common_byte_strings.h @@ -48,6 +48,10 @@ 0x06, 0xdd, 0xf6, 0xe1, 0xd7, 0x65, 0xa1, 0x93, 0xd9, 0xcb, 0xe1, 0x46, 0xce, 0xeb, 0x79, \ 0xac, 0x1c, 0xb4, 0x85, 0xed, 0x5f, 0x5b, 0x37, 0x91, 0x3a, 0x8c, 0xf5, 0x85, 0x7e, 0xff, \ 0x00, 0xa9 +#define PROGRAM_ID_SPL_TOKEN_2022 /* TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb */ \ + 0x06, 0xdd, 0xf6, 0xe1, 0xee, 0x75, 0x8f, 0xde, 0x18, 0x42, 0x5d, 0xbc, 0xe4, 0x6c, 0xcd, \ + 0xda, 0xb6, 0x1a, 0xfc, 0x4d, 0x83, 0xb9, 0x0d, 0x27, 0xfe, 0xbd, 0xf9, 0x28, 0xd8, 0xa1, \ + 0x8b, 0xfc #define PROGRAM_ID_SYSTEM BYTES32_BS58_1 #define PROGRAM_ID_STAKE /* "Stake11111111111111111111111111111111111111" */ \ 0x06, 0xa1, 0xd8, 0x17, 0x91, 0x37, 0x54, 0x2a, 0x98, 0x34, 0x37, 0xbd, 0xfe, 0x2a, 0x7a, \ diff --git a/libsol/include/spl/token.h b/libsol/include/spl/token.h index 857ceff0..f4245f02 100644 --- a/libsol/include/spl/token.h +++ b/libsol/include/spl/token.h @@ -100,6 +100,8 @@ typedef struct Token_COption_Pubkey { /** * Instructions supported by the token program. + * List is compliant with the program source code at: + * https://github.com/solana-labs/solana-program-library/blob/master/token/program-2022/src/instruction.rs */ typedef enum Token_TokenInstruction_Tag { /** @@ -439,6 +441,85 @@ typedef enum Token_TokenInstruction_Tag { * 0. `[writable]` The native token account to sync with its underlying lamports. */ Token_TokenInstruction_SyncNative, + + /** + * The common instruction prefix for Transfer Fee extension instructions. + * See `extension::transfer_fee::instruction::TransferFeeInstruction` for + * further details about the extended instructions that share this + * instruction prefix + */ + Token_TokenExtensionInstruction_TransferFeeExtension = 26, + + /** + * The common instruction prefix for Confidential Transfer extension instructions. + * See `extension::confidential_transfer::instruction::ConfidentialTransferInstruction` for + * further details about the extended instructions that share this + * instruction prefix + */ + Token_TokenExtensionInstruction_ConfidentialTransferExtension = 27, + + /** + * The common instruction prefix for Default Account State extension instructions. + * See `extension::default_account_state::instruction::DefaultAccountStateInstruction` for + * further details about the extended instructions that share this instruction prefix + */ + Token_TokenExtensionInstruction_DefaultAccountStateExtension = 28, + + /** + * The common instruction prefix for Memo Transfer account extension instructions. + * See `extension::memo_transfer::instruction::RequiredMemoTransfersInstruction` for + * further details about the extended instructions that share this instruction prefix + */ + Token_TokenExtensionInstruction_MemoTransferExtension = 30, + + /** + * The common instruction prefix for Interest Bearing extension instructions. + * See `extension::interest_bearing_mint::instruction::InterestBearingMintInstruction` for + * further details about the extended instructions that share this instruction prefix + */ + Token_TokenExtensionInstruction_InterestBearingMintExtension = 33, + + /** + * The common instruction prefix for CPI Guard account extension instructions. + * See `extension::cpi_guard::instruction::CpiGuardInstruction` for + * further details about the extended instructions that share this instruction prefix + */ + Token_TokenExtensionInstruction_CpiGuardExtension = 34, + + /** + * The common instruction prefix for transfer hook extension instructions. + * See `extension::transfer_hook::instruction::TransferHookInstruction` + * for further details about the extended instructions that share this instruction prefix + */ + Token_TokenExtensionInstruction_TransferHookExtension = 36, + + /** + * The common instruction prefix for the confidential transfer fee extension instructions. + * See `extension::confidential_transfer_fee::instruction::ConfidentialTransferFeeInstruction` + * for further details about the extended instructions that share this instruction prefix + */ + Token_TokenExtensionInstruction_ConfidentialTransferFeeExtension = 37, + + /** + * The common instruction prefix for metadata pointer extension instructions. + * See `extension::metadata_pointer::instruction::MetadataPointerInstruction` + * for further details about the extended instructions that share this instruction prefix + */ + Token_TokenExtensionInstruction_MetadataPointerExtension = 39, + + /** + * The common instruction prefix for group pointer extension instructions. + * See `extension::group_pointer::instruction::GroupPointerInstruction` + * for further details about the extended instructions that share this instruction prefix + */ + Token_TokenExtensionInstruction_GroupPointerExtension = 40, + + /** + * The common instruction prefix for group member pointer extension instructions. + * See `extension::group_member_pointer::instruction::GroupMemberPointerInstruction` + * for further details about the extended instructions that share this instruction prefix + */ + Token_TokenExtensionInstruction_GroupMemberPointerExtension = 41 } Token_TokenInstruction_Tag; typedef struct Token_TokenInstruction_Token_InitializeMint_Body { diff --git a/libsol/instruction.c b/libsol/instruction.c index fa9f2c70..4c8709a9 100644 --- a/libsol/instruction.c +++ b/libsol/instruction.c @@ -2,6 +2,7 @@ #include "serum_assert_owner_instruction.h" #include "spl_memo_instruction.h" #include "spl_token_instruction.h" +#include "spl_token2022_instruction.h" #include "compute_budget_instruction.h" #include "stake_instruction.h" #include "system_instruction.h" @@ -18,6 +19,8 @@ enum ProgramId instruction_program_id(const Instruction* instruction, const Mess return ProgramIdVote; } else if (memcmp(program_id, &spl_token_program_id, PUBKEY_SIZE) == 0) { return ProgramIdSplToken; + } else if(memcmp(program_id, &spl_token2022_program_id, PUBKEY_SIZE) == 0) { + return ProgramIdSplToken;//Treat the Token2022 exactly the same as the SplToken } else if (memcmp(program_id, &spl_associated_token_account_program_id, PUBKEY_SIZE) == 0) { return ProgramIdSplAssociatedTokenAccount; } else if (is_serum_assert_owner_program_id(program_id)) { diff --git a/libsol/message.c b/libsol/message.c index 77180c36..91fcfd2c 100644 --- a/libsol/message.c +++ b/libsol/message.c @@ -26,6 +26,10 @@ int process_message_body(const uint8_t* message_body, InstructionInfo instruction_info[MAX_INSTRUCTIONS]; explicit_bzero(instruction_info, sizeof(InstructionInfo) * MAX_INSTRUCTIONS); + //Track if given transaction contains token2022 extensions that are not fully supported + //Needed to display user proper warning + SplTokenExtensionsMetadata token_extensions_metadata = {false}; + size_t display_instruction_count = 0; InstructionInfo* display_instruction_info[MAX_INSTRUCTIONS]; @@ -36,6 +40,8 @@ int process_message_body(const uint8_t* message_body, BAIL_IF(instruction_validate(&instruction, header)); InstructionInfo* info = &instruction_info[instruction_count]; + bool ignore_instruction_info = false; + enum ProgramId program_id = instruction_program_id(&instruction, header); switch (program_id) { case ProgramIdSerumAssertOwner: { @@ -58,7 +64,12 @@ int process_message_body(const uint8_t* message_body, break; } case ProgramIdSplToken: - if (parse_spl_token_instructions(&instruction, header, &info->spl_token) == 0) { + if (parse_spl_token_instructions(&instruction, + header, + &info->spl_token, + &token_extensions_metadata, + &ignore_instruction_info) == 0) { + info->spl_token.is_token2022_kind = is_token2022_instruction(&instruction, header); info->kind = program_id; } break; @@ -89,6 +100,9 @@ int process_message_body(const uint8_t* message_body, case ProgramIdUnknown: break; } + if(ignore_instruction_info){ + continue; + } switch (info->kind) { case ProgramIdSplAssociatedTokenAccount: case ProgramIdSplToken: @@ -120,5 +134,8 @@ int process_message_body(const uint8_t* message_body, BAIL_IF(instruction_info[i].kind == ProgramIdUnknown); } + if (token_extensions_metadata.generate_extension_warning) { + BAIL_IF(print_spl_token_extension_warning()); + } return print_transaction(print_config, display_instruction_info, display_instruction_count); } diff --git a/libsol/spl_token2022_instruction.c b/libsol/spl_token2022_instruction.c new file mode 100644 index 00000000..8d882d9d --- /dev/null +++ b/libsol/spl_token2022_instruction.c @@ -0,0 +1,5 @@ +#include "sol/print_config.h" +#include "common_byte_strings.h" + + +const Pubkey spl_token2022_program_id = {{PROGRAM_ID_SPL_TOKEN_2022}}; diff --git a/libsol/spl_token2022_instruction.h b/libsol/spl_token2022_instruction.h new file mode 100644 index 00000000..d30e7505 --- /dev/null +++ b/libsol/spl_token2022_instruction.h @@ -0,0 +1,12 @@ +#pragma once + +#include "sol/parser.h" +#include "sol/print_config.h" +#include "sol/transaction_summary.h" +#include "spl/token.h" +#include "instruction.h" + +#define SplTokenExtensionKind(b) Token_TokenExtensionInstruction_##b + +extern const Pubkey spl_token2022_program_id; + diff --git a/libsol/spl_token2022_instruction_test.c b/libsol/spl_token2022_instruction_test.c new file mode 100644 index 00000000..f0ead84b --- /dev/null +++ b/libsol/spl_token2022_instruction_test.c @@ -0,0 +1,847 @@ +#include "common_byte_strings.h" +#include "instruction.h" +#include "spl_token2022_instruction.c" +#include +#include +#include +#include "util.h" + +/* + * This file is almost a copy of the spl_token_instruction_test.c file. + * It's main purpose is to test the compatibility of spl_token2022 instructions. + */ + +#define BLOCKHASH BYTES32_BS58_1 +#define MINT_ACCOUNT BYTES32_BS58_2 +#define TOKEN_ACCOUNT BYTES32_BS58_3 +#define OWNER_ACCOUNT BYTES32_BS58_4 +#define MULTISIG_ACCOUNT OWNER_ACCOUNT +#define SIGNER1 BYTES32_BS58_5 +#define SIGNER2 BYTES32_BS58_6 +#define SIGNER3 BYTES32_BS58_7 +#define DEST_ACCOUNT BYTES32_BS58_8 +#define DELEGATE DEST_ACCOUNT +#define NEW_OWNER DEST_ACCOUNT + +void test_parse_spl_token_create_token() { + uint8_t message[] = {2, + 0, + 3, + 5, + OWNER_ACCOUNT, + MINT_ACCOUNT, + SYSVAR_RENT, + PROGRAM_ID_SYSTEM, + PROGRAM_ID_SPL_TOKEN_2022, + BLOCKHASH, + 2, + 3, + 2, + 0, + 1, + 52, + 0, + 0, + 0, + 0, + 245, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 88, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + PROGRAM_ID_SPL_TOKEN_2022, + 4, + 2, + 1, + 2, + 35, + 0, + 9, + OWNER_ACCOUNT, + 0}; + + Parser parser = {message, sizeof(message)}; + MessageHeader header; + assert(parse_message_header(&parser, &header) == 0); + + Instruction instruction; + assert(parse_instruction(&parser, &instruction) == 0); // SystemCreateAccount (ignored) + assert(instruction_validate(&instruction, &header) == 0); + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenInitializeMint + assert(instruction_validate(&instruction, &header) == 0); + + SplTokenInfo info; + assert(parse_spl_token_instructions(&instruction, &header, &info) == 0); + assert(parser.buffer_length == 0); + + assert(info.kind == SplTokenKind(InitializeMint)); + + const SplTokenInitializeMintInfo* init_mint = &info.initialize_mint; + + const Pubkey mint_account = {{MINT_ACCOUNT}}; + assert_pubkey_equal(init_mint->mint_account, &mint_account); + + const Pubkey owner = {{OWNER_ACCOUNT}}; + assert_pubkey_equal(init_mint->mint_authority, &owner); + + assert(init_mint->decimals == 9); + + assert(init_mint->freeze_authority == NULL); +} + +void test_parse_spl_token_create_account() { + uint8_t message[] = { + 0x02, + 0x00, + 0x03, + 0x06, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + MINT_ACCOUNT, + SYSVAR_RENT, + PROGRAM_ID_SYSTEM, + PROGRAM_ID_SPL_TOKEN_2022, + BLOCKHASH, + 0x02, + // SystemCreateAccount + 0x04, + 0x02, + 0x00, + 0x01, + 0x34, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x56, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + PROGRAM_ID_SPL_TOKEN_2022, + // SplToken2022InitializeAccount + 0x05, + 0x04, + 0x01, + 0x02, + 0x00, + 0x03, + 0x01, + 0x01, + }; + + Parser parser = {message, sizeof(message)}; + MessageHeader header; + assert(parse_message_header(&parser, &header) == 0); + + Instruction instruction; + assert(parse_instruction(&parser, &instruction) == 0); // SystemCreateAccount (ignored) + assert(instruction_validate(&instruction, &header) == 0); + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenInitializeAccount + assert(instruction_validate(&instruction, &header) == 0); + + SplTokenInfo info; + assert(parse_spl_token_instructions(&instruction, &header, &info) == 0); + assert(parser.buffer_length == 0); + + assert(info.kind == SplTokenKind(InitializeAccount)); + const SplTokenInitializeAccountInfo* init_acc = &info.initialize_account; + + const Pubkey token_account = {{TOKEN_ACCOUNT}}; + assert_pubkey_equal(init_acc->token_account, &token_account); + + const Pubkey mint_account = {{MINT_ACCOUNT}}; + assert_pubkey_equal(init_acc->mint_account, &mint_account); + + const Pubkey owner = {{OWNER_ACCOUNT}}; + assert_pubkey_equal(init_acc->owner, &owner); +} + + +void test_parse_spl_token_create_account2() { + uint8_t message[] = {0x02, + 0x00, + 0x04, + 0x06, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + MINT_ACCOUNT, + SYSVAR_RENT, + PROGRAM_ID_SYSTEM, + PROGRAM_ID_SPL_TOKEN_2022, + BLOCKHASH, + 0x02, + // SystemCreateAccount + 0x04, + 0x02, + 0x00, + 0x01, + 0x34, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x56, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + PROGRAM_ID_SPL_TOKEN_2022, + // SplTokenInitializeAccount2 + 0x05, + 0x03, + 0x01, + 0x02, + 0x03, + 0x21, + 0x10, + OWNER_ACCOUNT}; + + Parser parser = {message, sizeof(message)}; + MessageHeader header; + assert(parse_message_header(&parser, &header) == 0); + + Instruction instruction; + assert(parse_instruction(&parser, &instruction) == 0); // SystemCreateAccount (ignored) + assert(instruction_validate(&instruction, &header) == 0); + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenInitializeAccount2 + assert(instruction_validate(&instruction, &header) == 0); + + SplTokenInfo info; + assert(parse_spl_token_instructions(&instruction, &header, &info) == 0); + assert(parser.buffer_length == 0); + + assert(info.kind == SplTokenKind(InitializeAccount2)); + const SplTokenInitializeAccountInfo* init_acc = &info.initialize_account; + + const Pubkey token_account = {{TOKEN_ACCOUNT}}; + assert_pubkey_equal(init_acc->token_account, &token_account); + + const Pubkey mint_account = {{MINT_ACCOUNT}}; + assert_pubkey_equal(init_acc->mint_account, &mint_account); + + const Pubkey owner = {{OWNER_ACCOUNT}}; + assert_pubkey_equal(init_acc->owner, &owner); +} + + +void test_parse_spl_token_create_multisig() { + uint8_t message[] = {2, + 0, + 5, + 8, + OWNER_ACCOUNT, + MULTISIG_ACCOUNT, + SYSVAR_RENT, + SIGNER1, + SIGNER2, + SIGNER3, + PROGRAM_ID_SYSTEM, + PROGRAM_ID_SPL_TOKEN_2022, + BLOCKHASH, + 2, + // SystemCreateAccount + 6, + 2, + 0, + 1, + 52, + 0, + 0, + 0, + 0, + 245, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 40, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + PROGRAM_ID_SPL_TOKEN_2022, + // SplTokenInitializeMultisig + 7, + 5, + 1, + 2, + 3, + 4, + 5, + 2, + 2, + 2}; + Parser parser = {message, sizeof(message)}; + MessageHeader header; + assert(parse_message_header(&parser, &header) == 0); + + Instruction instruction; + assert(parse_instruction(&parser, &instruction) == 0); // SystemCreateAccount (ignored) + assert(instruction_validate(&instruction, &header) == 0); + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenInitializeMultisig + assert(instruction_validate(&instruction, &header) == 0); + + SplTokenInfo info; + assert(parse_spl_token_instructions(&instruction, &header, &info) == 0); + assert(parser.buffer_length == 0); + + assert(info.kind == SplTokenKind(InitializeMultisig)); + const SplTokenInitializeMultisigInfo* init_ms = &info.initialize_multisig; + + assert(init_ms->body.m == 2); + + const Pubkey multisig_account = {{MULTISIG_ACCOUNT}}; + assert_pubkey_equal(init_ms->multisig_account, &multisig_account); + + assert(init_ms->signers.count == 3); + const Pubkey* signer = init_ms->signers.first; + const Pubkey signer1 = {{SIGNER1}}; + assert_pubkey_equal(signer++, &signer1); + const Pubkey signer2 = {{SIGNER2}}; + assert_pubkey_equal(signer++, &signer2); + const Pubkey signer3 = {{SIGNER3}}; + assert_pubkey_equal(signer++, &signer3); +} + + +void test_parse_spl_token_transfer() { + uint8_t message[] = {1, + 0, + 2, + 5, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + DEST_ACCOUNT, + MINT_ACCOUNT, + PROGRAM_ID_SPL_TOKEN_2022, + BLOCKHASH, + 1, + 4, + 4, + 1, + 3, + 2, + 0, + 10, + 12, + 42, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 9}; + Parser parser = {message, sizeof(message)}; + MessageHeader header; + assert(parse_message_header(&parser, &header) == 0); + + Instruction instruction; + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenTransfer2 + assert(instruction_validate(&instruction, &header) == 0); + + SplTokenInfo info; + assert(parse_spl_token_instructions(&instruction, &header, &info) == 0); + assert(parser.buffer_length == 0); + + assert(info.kind == SplTokenKind(TransferChecked)); + const SplTokenTransferInfo* tr_info = &info.transfer; + + assert(tr_info->body.amount == 42); + assert(tr_info->body.decimals == 9); + + const Pubkey src_account = {{TOKEN_ACCOUNT}}; + assert_pubkey_equal(tr_info->src_account, &src_account); + + const Pubkey dest_account = {{DEST_ACCOUNT}}; + assert_pubkey_equal(tr_info->dest_account, &dest_account); + + const Pubkey owner = {{OWNER_ACCOUNT}}; + assert_pubkey_equal(tr_info->sign.single.signer, &owner); + + const Pubkey mint_account = {{MINT_ACCOUNT}}; + assert_pubkey_equal(tr_info->mint_account, &mint_account); +} + + +void test_parse_spl_token_approve() { + uint8_t message[] = {1, + 0, + 2, + 4, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + PROGRAM_ID_SPL_TOKEN_2022, + DEST_ACCOUNT, + BLOCKHASH, + 1, + 2, + 4, + 1, + 2, + 3, + 0, + 10, + 13, + 42, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 9}; + Parser parser = {message, sizeof(message)}; + MessageHeader header; + assert(parse_message_header(&parser, &header) == 0); + + Instruction instruction; + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenApprove2 + assert(instruction_validate(&instruction, &header) == 0); + + SplTokenInfo info; + assert(parse_spl_token_instructions(&instruction, &header, &info) == 0); + assert(parser.buffer_length == 0); + + assert(info.kind == SplTokenKind(ApproveChecked)); + const SplTokenApproveInfo* ap_info = &info.approve; + + assert(ap_info->body.amount == 42); + assert(ap_info->body.decimals == 9); + + const Pubkey token_account = {{TOKEN_ACCOUNT}}; + assert_pubkey_equal(ap_info->token_account, &token_account); + + const Pubkey delegate = {{DELEGATE}}; + assert_pubkey_equal(ap_info->delegate, &delegate); + + const Pubkey owner = {{OWNER_ACCOUNT}}; + assert_pubkey_equal(ap_info->sign.single.signer, &owner); + + const Pubkey mint_account = {{PROGRAM_ID_SPL_TOKEN_2022}}; + assert_pubkey_equal(ap_info->mint_account, &mint_account); +} + + +void test_parse_spl_token_revoke() { + uint8_t message[] = {1, + 0, + 2, + 3, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + PROGRAM_ID_SPL_TOKEN_2022, + BLOCKHASH, + 1, + 2, + 2, + 1, + 0, + 1, + 5}; + Parser parser = {message, sizeof(message)}; + MessageHeader header; + assert(parse_message_header(&parser, &header) == 0); + + Instruction instruction; + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenRevoke + assert(instruction_validate(&instruction, &header) == 0); + + SplTokenInfo info; + assert(parse_spl_token_instructions(&instruction, &header, &info) == 0); + assert(parser.buffer_length == 0); + + assert(info.kind == SplTokenKind(Revoke)); + const SplTokenRevokeInfo* re_info = &info.revoke; + + const Pubkey token_account = {{TOKEN_ACCOUNT}}; + assert_pubkey_equal(re_info->token_account, &token_account); + + const Pubkey owner = {{OWNER_ACCOUNT}}; + assert_pubkey_equal(re_info->sign.single.signer, &owner); +} + + +void test_parse_spl_token_set_authority() { + uint8_t message[] = {1, + 0, + 1, + 3, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + PROGRAM_ID_SPL_TOKEN_2022, + BLOCKHASH, + 1, + 2, + 2, + 1, + 0, + 35, + 6, + 2, + 1, + NEW_OWNER}; + Parser parser = {message, sizeof(message)}; + MessageHeader header; + assert(parse_message_header(&parser, &header) == 0); + + Instruction instruction; + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenSetAuthority + assert(instruction_validate(&instruction, &header) == 0); + + SplTokenInfo info; + assert(parse_spl_token_instructions(&instruction, &header, &info) == 0); + assert(parser.buffer_length == 0); + + assert(info.kind == SplTokenKind(SetAuthority)); + const SplTokenSetAuthorityInfo* so_info = &info.set_owner; + + const Pubkey token_account = {{TOKEN_ACCOUNT}}; + assert_pubkey_equal(so_info->account, &token_account); + + assert(so_info->authority_type == Token_AuthorityType_AccountOwner); + + const Pubkey new_owner = {{NEW_OWNER}}; + assert_pubkey_equal(so_info->new_authority, &new_owner); + + const Pubkey owner = {{OWNER_ACCOUNT}}; + assert_pubkey_equal(so_info->sign.single.signer, &owner); +} + + +void test_parse_spl_token_mint_to() { + uint8_t message[] = {1, + 0, + 0, + 3, + OWNER_ACCOUNT, + PROGRAM_ID_SPL_TOKEN_2022, + TOKEN_ACCOUNT, + BLOCKHASH, + 1, + 1, + 3, + 1, + 2, + 0, + 10, + 14, + 42, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 9}; + Parser parser = {message, sizeof(message)}; + MessageHeader header; + assert(parse_message_header(&parser, &header) == 0); + + Instruction instruction; + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenMintTo2 + assert(instruction_validate(&instruction, &header) == 0); + + SplTokenInfo info; + assert(parse_spl_token_instructions(&instruction, &header, &info) == 0); + assert(parser.buffer_length == 0); + + assert(info.kind == SplTokenKind(MintToChecked)); + const SplTokenMintToInfo* mt_info = &info.mint_to; + + assert(mt_info->body.amount == 42); + assert(mt_info->body.decimals == 9); + + const Pubkey mint_account = {{PROGRAM_ID_SPL_TOKEN_2022}}; + assert_pubkey_equal(mt_info->mint_account, &mint_account); + + const Pubkey token_account = {{TOKEN_ACCOUNT}}; + assert_pubkey_equal(mt_info->token_account, &token_account); + + const Pubkey owner = {{OWNER_ACCOUNT}}; + assert_pubkey_equal(mt_info->sign.single.signer, &owner); +} + + +void test_parse_spl_token_burn() { + uint8_t message[] = {1, + 0, + 0, + 4, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + MINT_ACCOUNT, + PROGRAM_ID_SPL_TOKEN_2022, + BLOCKHASH, + 1, + 3, + 3, + 1, + 2, + 0, + 10, + 15, + 42, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 9}; + Parser parser = {message, sizeof(message)}; + MessageHeader header; + assert(parse_message_header(&parser, &header) == 0); + + Instruction instruction; + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenBurn + assert(instruction_validate(&instruction, &header) == 0); + + SplTokenInfo info; + assert(parse_spl_token_instructions(&instruction, &header, &info) == 0); + assert(parser.buffer_length == 0); + + assert(info.kind == SplTokenKind(BurnChecked)); + const SplTokenBurnInfo* bn_info = &info.burn; + + assert(bn_info->body.amount == 42); + assert(bn_info->body.decimals == 9); + + const Pubkey token_account = {{TOKEN_ACCOUNT}}; + assert_pubkey_equal(bn_info->token_account, &token_account); + + const Pubkey owner = {{OWNER_ACCOUNT}}; + assert_pubkey_equal(bn_info->sign.single.signer, &owner); + + const Pubkey mint_account = {{MINT_ACCOUNT}}; + assert_pubkey_equal(bn_info->mint_account, &mint_account); +} + +void test_parse_spl_token_close_account() { + uint8_t message[] = { + 0x01, + 0x00, + 0x01, + 0x03, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + PROGRAM_ID_SPL_TOKEN_2022, + BLOCKHASH, + 0x01, + // SplTokenCloseAccount + 0x02, + 0x03, + 0x01, + 0x00, + 0x00, + 0x01, + 0x09, + }; + Parser parser = {message, sizeof(message)}; + MessageHeader header; + assert(parse_message_header(&parser, &header) == 0); + + Instruction instruction; + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenCloseAccount + assert(instruction_validate(&instruction, &header) == 0); + + SplTokenInfo info; + assert(parse_spl_token_instructions(&instruction, &header, &info) == 0); + assert(parser.buffer_length == 0); + + assert(info.kind == SplTokenKind(CloseAccount)); + const SplTokenCloseAccountInfo* close_acc = &info.close_account; + + const Pubkey token_account = {{TOKEN_ACCOUNT}}; + assert_pubkey_equal(close_acc->token_account, &token_account); + + const Pubkey owner = {{OWNER_ACCOUNT}}; + assert_pubkey_equal(close_acc->dest_account, &owner); + + assert_pubkey_equal(close_acc->sign.single.signer, &owner); +} + +void test_parse_spl_token_freeze_account() { + uint8_t message[] = {1, + 0, + 2, + 4, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + MINT_ACCOUNT, + PROGRAM_ID_SPL_TOKEN_2022, + BLOCKHASH, + 1, + 3, + 3, + 1, + 2, + 0, + 1, + 10}; + Parser parser = {message, sizeof(message)}; + MessageHeader header; + assert(parse_message_header(&parser, &header) == 0); + + Instruction instruction; + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenFreezeAccount + assert(instruction_validate(&instruction, &header) == 0); + + SplTokenInfo info; + assert(parse_spl_token_instructions(&instruction, &header, &info) == 0); + assert(parser.buffer_length == 0); + + assert(info.kind == SplTokenKind(FreezeAccount)); + const SplTokenFreezeAccountInfo* freeze_account = &info.freeze_account; + + const Pubkey token_account = {{TOKEN_ACCOUNT}}; + assert_pubkey_equal(freeze_account->token_account, &token_account); + + const Pubkey mint_account = {{MINT_ACCOUNT}}; + assert_pubkey_equal(freeze_account->mint_account, &mint_account); + + const Pubkey owner = {{OWNER_ACCOUNT}}; + assert_pubkey_equal(freeze_account->sign.single.signer, &owner); +} + +void test_parse_spl_token_thaw_account() { + uint8_t message[] = {1, + 0, + 2, + 4, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + MINT_ACCOUNT, + PROGRAM_ID_SPL_TOKEN_2022, + BLOCKHASH, + 1, + 3, + 3, + 1, + 2, + 0, + 1, + 11}; + Parser parser = {message, sizeof(message)}; + MessageHeader header; + assert(parse_message_header(&parser, &header) == 0); + + Instruction instruction; + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenThawAccount + assert(instruction_validate(&instruction, &header) == 0); + + SplTokenInfo info; + assert(parse_spl_token_instructions(&instruction, &header, &info) == 0); + assert(parser.buffer_length == 0); + + assert(info.kind == SplTokenKind(ThawAccount)); + const SplTokenThawAccountInfo* thaw_account = &info.thaw_account; + + const Pubkey token_account = {{TOKEN_ACCOUNT}}; + assert_pubkey_equal(thaw_account->token_account, &token_account); + + const Pubkey mint_account = {{MINT_ACCOUNT}}; + assert_pubkey_equal(thaw_account->mint_account, &mint_account); + + const Pubkey owner = {{OWNER_ACCOUNT}}; + assert_pubkey_equal(thaw_account->sign.single.signer, &owner); +} + +void test_parse_spl_token_sync_native() { + uint8_t message[] = {1, + 0, + 1, + 4, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + PROGRAM_ID_SPL_TOKEN_2022, + BLOCKHASH, + 1, + 2, + 1, + 1, + 1, + 17}; + Parser parser = {message, sizeof(message)}; + MessageHeader header; + assert(parse_message_header(&parser, &header) == 0); + + Instruction instruction; + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenSyncNative + assert(instruction_validate(&instruction, &header) == 0); + + SplTokenInfo info; + assert(parse_spl_token_instructions(&instruction, &header, &info) == 0); + assert(parser.buffer_length == 0); + + assert(info.kind == SplTokenKind(SyncNative)); + const SplTokenSyncNativeInfo* sync_native = &info.sync_native; + + const Pubkey token_account = {{TOKEN_ACCOUNT}}; + assert_pubkey_equal(sync_native->token_account, &token_account); +} + + +int main(){ + + test_parse_spl_token_create_token(); + test_parse_spl_token_create_account(); + test_parse_spl_token_create_account2(); + test_parse_spl_token_create_multisig(); + test_parse_spl_token_transfer(); + test_parse_spl_token_approve(); + test_parse_spl_token_revoke(); + test_parse_spl_token_set_authority(); + test_parse_spl_token_mint_to(); + test_parse_spl_token_burn(); + test_parse_spl_token_close_account(); + test_parse_spl_token_freeze_account(); + test_parse_spl_token_thaw_account(); + + printf("passed\n"); + return 0; +} \ No newline at end of file diff --git a/libsol/spl_token_instruction.c b/libsol/spl_token_instruction.c index 91d8c4d8..29acf918 100644 --- a/libsol/spl_token_instruction.c +++ b/libsol/spl_token_instruction.c @@ -3,6 +3,7 @@ #include "sol/parser.h" #include "sol/transaction_summary.h" #include "spl_token_instruction.h" +#include "spl_token2022_instruction.h" #include "token_info.h" #include "util.h" @@ -26,6 +27,19 @@ static int parse_spl_token_instruction_kind(Parser* parser, SplTokenInstructionK case SplTokenKind(FreezeAccount): case SplTokenKind(ThawAccount): case SplTokenKind(SyncNative): + + //Token2022 extensions + case SplTokenExtensionKind(TransferFeeExtension): + case SplTokenExtensionKind(ConfidentialTransferExtension): + case SplTokenExtensionKind(DefaultAccountStateExtension): + case SplTokenExtensionKind(MemoTransferExtension): + case SplTokenExtensionKind(InterestBearingMintExtension): + case SplTokenExtensionKind(CpiGuardExtension): + case SplTokenExtensionKind(TransferHookExtension): + case SplTokenExtensionKind(ConfidentialTransferFeeExtension): + case SplTokenExtensionKind(MetadataPointerExtension): + case SplTokenExtensionKind(GroupPointerExtension): + case SplTokenExtensionKind(GroupMemberPointerExtension): *kind = (SplTokenInstructionKind) maybe_kind; return 0; // Deprecated instructions @@ -326,7 +340,9 @@ static int parse_sync_native_spl_token_instruction(const Instruction* instructio int parse_spl_token_instructions(const Instruction* instruction, const MessageHeader* header, - SplTokenInfo* info) { + SplTokenInfo* info, + SplTokenExtensionsMetadata* token_extensions_metadata, + bool* ignore_instruction_info) { Parser parser = {instruction->data, instruction->data_length}; BAIL_IF(parse_spl_token_instruction_kind(&parser, &info->kind)); @@ -392,6 +408,26 @@ int parse_spl_token_instructions(const Instruction* instruction, return parse_burn_spl_token_instruction(&parser, instruction, header, &info->burn); case SplTokenKind(SyncNative): return parse_sync_native_spl_token_instruction(instruction, header, &info->sync_native); + + // Currently we do not need to parse these extensions in any way + case SplTokenExtensionKind(TransferFeeExtension): + case SplTokenExtensionKind(ConfidentialTransferExtension): + case SplTokenExtensionKind(MemoTransferExtension): + case SplTokenExtensionKind(TransferHookExtension): + case SplTokenExtensionKind(ConfidentialTransferFeeExtension): + // Mark that we have encountered not fully supported extension + token_extensions_metadata->generate_extension_warning = true; + __attribute__((fallthrough)); + case SplTokenExtensionKind(DefaultAccountStateExtension): + case SplTokenExtensionKind(InterestBearingMintExtension): + case SplTokenExtensionKind(CpiGuardExtension): + case SplTokenExtensionKind(MetadataPointerExtension): + case SplTokenExtensionKind(GroupPointerExtension): + case SplTokenExtensionKind(GroupMemberPointerExtension): + //Don't generate any screens for the user for any extension + *ignore_instruction_info = true; + return 0; + // Deprecated instructions case SplTokenKind(Transfer): case SplTokenKind(Approve): @@ -486,6 +522,7 @@ static int print_spl_token_initialize_multisig_info(const char* primary_title, int print_spl_token_transfer_info(const SplTokenTransferInfo* info, const PrintConfig* print_config, + bool is_token2022_kind, bool primary) { SummaryItem* item; @@ -508,6 +545,14 @@ int print_spl_token_transfer_info(const SplTokenTransferInfo* info, item = transaction_summary_general_item(); summary_item_set_pubkey(item, "To", info->dest_account); + if(is_token2022_kind){ + item = transaction_summary_general_item(); + summary_item_set_string(item, "Extension warning", ""); + + item = transaction_summary_general_item(); + summary_item_set_string(item, "", "Can't check mint extensions - Check explorer"); + } + print_spl_token_sign(&info->sign, print_config); return 0; @@ -715,7 +760,7 @@ int print_spl_token_info(const SplTokenInfo* info, const PrintConfig* print_conf case SplTokenKind(ThawAccount): return print_spl_token_thaw_account_info(&info->thaw_account, print_config); case SplTokenKind(TransferChecked): - return print_spl_token_transfer_info(&info->transfer, print_config, true); + return print_spl_token_transfer_info(&info->transfer, print_config, info->is_token2022_kind, true); case SplTokenKind(ApproveChecked): return print_spl_token_approve_info(&info->approve, print_config); case SplTokenKind(MintToChecked): @@ -724,6 +769,20 @@ int print_spl_token_info(const SplTokenInfo* info, const PrintConfig* print_conf return print_spl_token_burn_info(&info->burn, print_config); case SplTokenKind(SyncNative): return print_spl_token_sync_native_info(&info->sync_native, print_config); + + //For now, we don't display any information about the extensions + case SplTokenExtensionKind(TransferFeeExtension): + case SplTokenExtensionKind(ConfidentialTransferExtension): + case SplTokenExtensionKind(DefaultAccountStateExtension): + case SplTokenExtensionKind(MemoTransferExtension): + case SplTokenExtensionKind(InterestBearingMintExtension): + case SplTokenExtensionKind(CpiGuardExtension): + case SplTokenExtensionKind(TransferHookExtension): + case SplTokenExtensionKind(ConfidentialTransferFeeExtension): + case SplTokenExtensionKind(MetadataPointerExtension): + case SplTokenExtensionKind(GroupPointerExtension): + case SplTokenExtensionKind(GroupMemberPointerExtension): + // Deprecated instructions case SplTokenKind(Transfer): case SplTokenKind(Approve): @@ -770,3 +829,8 @@ const Pubkey* spl_token_option_pubkey_get(const SplTokenOptionPubkey* option_pub } return NULL; } + +bool is_token2022_instruction(const Instruction* instruction, const MessageHeader* header) { + const Pubkey* program_id = &header->pubkeys[instruction->program_id_index]; + return memcmp(program_id, &spl_token2022_program_id, PUBKEY_SIZE) == 0; +} \ No newline at end of file diff --git a/libsol/spl_token_instruction.h b/libsol/spl_token_instruction.h index 0c13f0f7..1c4757d7 100644 --- a/libsol/spl_token_instruction.h +++ b/libsol/spl_token_instruction.h @@ -119,6 +119,7 @@ typedef struct SplTokenSyncNativeInfo { typedef struct SplTokenInfo { SplTokenInstructionKind kind; + bool is_token2022_kind; union { SplTokenInitializeMintInfo initialize_mint; SplTokenInitializeAccountInfo initialize_account; @@ -136,9 +137,17 @@ typedef struct SplTokenInfo { }; } SplTokenInfo; +typedef struct SplTokenExtensionsMetadata{ + bool generate_extension_warning; +} SplTokenExtensionsMetadata; + +bool is_token2022_instruction(const Instruction* instruction, const MessageHeader* header); + int parse_spl_token_instructions(const Instruction* instruction, const MessageHeader* header, - SplTokenInfo* info); + SplTokenInfo* info, + SplTokenExtensionsMetadata *token_extensions_metadata, + bool* ignore_instruction_info); int print_spl_token_info(const SplTokenInfo* info, const PrintConfig* print_config); void summary_item_set_multisig_m_of_n(SummaryItem* item, uint8_t m, uint8_t n); @@ -150,4 +159,5 @@ const Pubkey* spl_token_option_pubkey_get(const SplTokenOptionPubkey* option_pub int print_spl_token_transfer_info(const SplTokenTransferInfo* info, const PrintConfig* print_config, + bool is_token2022_kind, bool primary); diff --git a/libsol/stake_instruction.c b/libsol/stake_instruction.c index a932c93d..02f1fa7f 100644 --- a/libsol/stake_instruction.c +++ b/libsol/stake_instruction.c @@ -459,7 +459,7 @@ static int print_stake_set_lockup_info(const StakeSetLockupInfo* info, return 0; } -static int print_stake_split_info(const StakeSplitInfo* info, const PrintConfig* print_config) { +int print_stake_split_info(const StakeSplitInfo* info, const PrintConfig* print_config) { BAIL_IF(print_stake_split_info1(info, print_config)); return print_stake_split_info2(info, print_config); } diff --git a/libsol/stake_instruction.h b/libsol/stake_instruction.h index 1bdcac6d..0498a8ce 100644 --- a/libsol/stake_instruction.h +++ b/libsol/stake_instruction.h @@ -118,6 +118,7 @@ int print_stake_info(const StakeInfo* info, const PrintConfig* print_config); int print_stake_initialize_info(const char* primary_title, const StakeInitializeInfo* info, const PrintConfig* print_config); +int print_stake_split_info(const StakeSplitInfo* info, const PrintConfig* print_config); int print_stake_split_info1(const StakeSplitInfo* info, const PrintConfig* print_config); diff --git a/libsol/system_instruction.c b/libsol/system_instruction.c index 87ecc8db..5f3137ce 100644 --- a/libsol/system_instruction.c +++ b/libsol/system_instruction.c @@ -274,6 +274,22 @@ static int print_system_transfer_info(const SystemTransferInfo* info, return 0; } +int print_system_prefund_for_split(const SystemInfo* info, + const PrintConfig* print_config) { + if (print_config->expert_mode) { + const SystemTransferInfo* transfer_info = &info->transfer; + SummaryItem* item; + + item = transaction_summary_general_item(); + summary_item_set_amount(item, "Prefund", transfer_info->lamports); + + item = transaction_summary_general_item(); + summary_item_set_pubkey(item, "Prefunder", transfer_info->from); + } + + return 0; +} + static int print_system_advance_nonce_account(const SystemAdvanceNonceInfo* info, const PrintConfig* print_config) { SummaryItem* item; diff --git a/libsol/system_instruction.h b/libsol/system_instruction.h index fdc82f00..e87cdfec 100644 --- a/libsol/system_instruction.h +++ b/libsol/system_instruction.h @@ -111,6 +111,7 @@ int print_system_create_account_with_seed_info(const char* primary_title, int print_system_initialize_nonce_info(const char* primary_title, const SystemInitializeNonceInfo* info, const PrintConfig* print_config); +int print_system_prefund_for_split(const SystemInfo* info, const PrintConfig* print_config); int print_system_allocate_with_seed_info(const char* primary_title, const SystemAllocateWithSeedInfo* info, const PrintConfig* print_config); diff --git a/libsol/transaction_printers.c b/libsol/transaction_printers.c index c140ba61..0e3d29da 100644 --- a/libsol/transaction_printers.c +++ b/libsol/transaction_printers.c @@ -87,6 +87,23 @@ const InstructionBrief stake_split_with_seed_brief_v1_2[] = { #define is_stake_split_with_seed_v1_2(infos, infos_length) \ instruction_infos_match_briefs(infos, stake_split_with_seed_brief_v1_2, infos_length) +const InstructionBrief stake_split_brief_v1_3[] = { + SYSTEM_IX_BRIEF(SystemTransfer), + SYSTEM_IX_BRIEF(SystemAllocate), + SYSTEM_IX_BRIEF(SystemAssign), + STAKE_IX_BRIEF(StakeSplit), +}; +#define is_stake_split_v1_3(infos, infos_length) \ + instruction_infos_match_briefs(infos, stake_split_brief_v1_3, infos_length) + +const InstructionBrief stake_split_with_seed_brief_v1_3[] = { + SYSTEM_IX_BRIEF(SystemTransfer), + SYSTEM_IX_BRIEF(SystemAllocateWithSeed), + STAKE_IX_BRIEF(StakeSplit), +}; +#define is_stake_split_with_seed_v1_3(infos, infos_length) \ + instruction_infos_match_briefs(infos, stake_split_with_seed_brief_v1_3, infos_length) + const InstructionBrief stake_authorize_both_brief[] = { STAKE_IX_BRIEF(StakeAuthorize), STAKE_IX_BRIEF(StakeAuthorize), @@ -288,6 +305,28 @@ static int print_stake_split_with_seed(const PrintConfig* print_config, return 0; } +static int print_prefunded_split(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { + UNUSED(infos_length); + + BAIL_IF(print_system_prefund_for_split(&infos[0]->system, print_config)); + BAIL_IF(print_stake_split_info(&infos[3]->stake.split, print_config)); + + return 0; +} + +static int print_prefunded_split_with_seed(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { + UNUSED(infos_length); + + BAIL_IF(print_system_prefund_for_split(&infos[0]->system, print_config)); + BAIL_IF(print_stake_split_with_seed(print_config, &infos[1], 2, true)); + + return 0; +} + static int print_stake_authorize_both(const PrintConfig* print_config, InstructionInfo* const* infos, size_t infos_length) { @@ -524,10 +563,11 @@ static int print_spl_associated_token_account_create_with_transfer(const PrintCo const SplAssociatedTokenAccountCreateInfo* c_info = &infos[0]->spl_associated_token_account.create; - const SplTokenTransferInfo* t_info = &infos[1]->spl_token.transfer; + SplTokenInfo spl_token = infos[1]->spl_token; + const SplTokenTransferInfo* t_info = &spl_token.transfer; print_spl_associated_token_account_create_info(c_info, print_config); - print_spl_token_transfer_info(t_info, print_config, false); + print_spl_token_transfer_info(t_info, print_config, spl_token.is_token2022_kind, false); return 0; } @@ -613,6 +653,13 @@ static int print_transaction_nonce_processed(const PrintConfig* print_config, // System allocate/assign have no interesting info, print // stake split as if it were a single instruction return print_stake_info(&infos[2]->stake, print_config); + } else if(is_stake_split_with_seed_v1_3(infos, infos_length)) { + return print_prefunded_split_with_seed(print_config, infos, infos_length); + } + break; + case 4: + if(is_stake_split_v1_3(infos, infos_length)) { + return print_prefunded_split(print_config, infos, infos_length); } break; @@ -623,6 +670,16 @@ static int print_transaction_nonce_processed(const PrintConfig* print_config, return 1; } +int print_spl_token_extension_warning(){ + + SummaryItem* item = transaction_summary_general_item(); + summary_item_set_string(item, "Extension Warning", "Unsupported extensions found"); + item = transaction_summary_general_item(); + summary_item_set_string(item, "","Verify transaction before signing"); + + return 0; +} + int print_transaction(const PrintConfig* print_config, InstructionInfo* const* infos, size_t infos_length) { diff --git a/libsol/transaction_printers.h b/libsol/transaction_printers.h index c8eb41c9..b710ae6f 100644 --- a/libsol/transaction_printers.h +++ b/libsol/transaction_printers.h @@ -5,3 +5,5 @@ int print_transaction(const PrintConfig* print_config, InstructionInfo* const* infos, size_t infos_length); + +int print_spl_token_extension_warning(); \ No newline at end of file diff --git a/src/main.c b/src/main.c index 3717d8d8..ba88e23f 100644 --- a/src/main.c +++ b/src/main.c @@ -210,7 +210,7 @@ void coin_main(void) { #ifdef HAVE_BLE BLE_power(0, NULL); - BLE_power(1, "Nano X"); + BLE_power(1, NULL); #endif // HAVE_BLE app_main(); @@ -247,13 +247,12 @@ static void start_app_from_lib(void) { // grab the current plane mode setting G_io_app.plane_mode = os_setting_get(OS_SETTING_PLANEMODE, NULL, 0); BLE_power(0, NULL); - BLE_power(1, "Nano X"); + BLE_power(1, NULL); #endif // HAVE_BLE app_main(); } static void library_main_helper(libargs_t *args) { - check_api_level(CX_COMPAT_APILEVEL); switch (args->command) { case CHECK_ADDRESS: // ensure result is zero if an exception is thrown diff --git a/src/utils.c b/src/utils.c index a1696bdf..234bcd04 100644 --- a/src/utils.c +++ b/src/utils.c @@ -2,99 +2,39 @@ #include "cx.h" #include #include + +#include "lib_standard_app/crypto_helpers.h" + #include "utils.h" -void get_public_key(uint8_t *publicKeyArray, const uint32_t *derivationPath, size_t pathLength) { - cx_ecfp_private_key_t privateKey; - cx_ecfp_public_key_t publicKey; +void get_public_key(uint8_t publicKeyArray[static PUBKEY_LENGTH], + const uint32_t *derivationPath, + size_t pathLength) { + uint8_t rawPubkey[65]; + cx_err_t cx_err; - get_private_key(&privateKey, derivationPath, pathLength); - BEGIN_TRY { - TRY { - cx_ecfp_generate_pair(CX_CURVE_Ed25519, &publicKey, &privateKey, 1); - } - CATCH_OTHER(e) { - MEMCLEAR(privateKey); - THROW(e); - } - FINALLY { - MEMCLEAR(privateKey); - } + cx_err = bip32_derive_with_seed_get_pubkey_256(HDW_ED25519_SLIP10, + CX_CURVE_Ed25519, + derivationPath, + pathLength, + rawPubkey, + NULL, + CX_SHA512, + NULL, + 0); + + if (CX_OK != cx_err) { + THROW(cx_err); } - END_TRY; for (int i = 0; i < PUBKEY_LENGTH; i++) { - publicKeyArray[i] = publicKey.W[PUBKEY_LENGTH + PRIVATEKEY_LENGTH - i]; + publicKeyArray[i] = rawPubkey[PUBKEY_LENGTH + PRIVATEKEY_LENGTH - i]; } - if ((publicKey.W[PUBKEY_LENGTH] & 1) != 0) { + if ((rawPubkey[PUBKEY_LENGTH] & 1) != 0) { publicKeyArray[PUBKEY_LENGTH - 1] |= 0x80; } } -uint32_t readUint32BE(uint8_t *buffer) { - return ((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3])); -} - -void get_private_key(cx_ecfp_private_key_t *privateKey, - const uint32_t *derivationPath, - size_t pathLength) { - uint8_t privateKeyData[PRIVATEKEY_LENGTH]; - BEGIN_TRY { - TRY { - os_perso_derive_node_bip32_seed_key(HDW_ED25519_SLIP10, - CX_CURVE_Ed25519, - derivationPath, - pathLength, - privateKeyData, - NULL, - NULL, - 0); - cx_ecfp_init_private_key(CX_CURVE_Ed25519, - privateKeyData, - PRIVATEKEY_LENGTH, - privateKey); - } - CATCH_OTHER(e) { - MEMCLEAR(privateKeyData); - THROW(e); - } - FINALLY { - MEMCLEAR(privateKeyData); - } - } - END_TRY; -} - -void get_private_key_with_seed(cx_ecfp_private_key_t *privateKey, - const uint32_t *derivationPath, - uint8_t pathLength) { - uint8_t privateKeyData[PRIVATEKEY_LENGTH]; - BEGIN_TRY { - TRY { - os_perso_derive_node_bip32_seed_key(HDW_ED25519_SLIP10, - CX_CURVE_Ed25519, - derivationPath, - pathLength, - privateKeyData, - NULL, - (unsigned char *) "ed25519 seed", - 12); - cx_ecfp_init_private_key(CX_CURVE_Ed25519, - privateKeyData, - PRIVATEKEY_LENGTH, - privateKey); - } - CATCH_OTHER(e) { - MEMCLEAR(privateKeyData); - THROW(e); - } - FINALLY { - MEMCLEAR(privateKeyData); - } - } - END_TRY; -} - int read_derivation_path(const uint8_t *data_buffer, size_t data_size, uint32_t *derivation_path, @@ -126,32 +66,24 @@ int read_derivation_path(const uint8_t *data_buffer, } uint8_t set_result_sign_message(void) { - uint8_t signature[SIGNATURE_LENGTH]; - cx_ecfp_private_key_t privateKey; - BEGIN_TRY { - TRY { - get_private_key_with_seed(&privateKey, - G_command.derivation_path, - G_command.derivation_path_length); - cx_eddsa_sign(&privateKey, - CX_LAST, - CX_SHA512, - G_command.message, - G_command.message_length, - NULL, - 0, - signature, - SIGNATURE_LENGTH, - NULL); - memcpy(G_io_apdu_buffer, signature, SIGNATURE_LENGTH); - } - CATCH_OTHER(e) { - THROW(e); - } - FINALLY { - MEMCLEAR(privateKey); - } + size_t sigLen = SIGNATURE_LENGTH; + cx_err_t cx_err; + + cx_err = bip32_derive_with_seed_eddsa_sign_hash_256(HDW_ED25519_SLIP10, + CX_CURVE_Ed25519, + G_command.derivation_path, + G_command.derivation_path_length, + CX_SHA512, + G_command.message, + G_command.message_length, + G_io_apdu_buffer, + &sigLen, + NULL, + 0); + + if (CX_OK != cx_err) { + THROW(cx_err); } - END_TRY; + return SIGNATURE_LENGTH; } diff --git a/src/utils.h b/src/utils.h index 6961b711..ad0981c8 100644 --- a/src/utils.h +++ b/src/utils.h @@ -21,17 +21,9 @@ typedef enum rlpTxType { TX_FEE } rlpTxType; -void get_public_key(uint8_t *publicKeyArray, const uint32_t *derivationPath, size_t pathLength); - -uint32_t readUint32BE(uint8_t *buffer); - -void get_private_key(cx_ecfp_private_key_t *privateKey, - const uint32_t *derivationPath, - size_t pathLength); - -void get_private_key_with_seed(cx_ecfp_private_key_t *privateKey, - const uint32_t *derivationPath, - uint8_t pathLength); +void get_public_key(uint8_t publicKeyArray[static PUBKEY_LENGTH], + const uint32_t *derivationPath, + size_t pathLength); /** * Deserialize derivation path from raw bytes. diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_1/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_1/00000.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_1/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_1/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_1/00001.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_1/00001.png index ab88bd3a..d885fe67 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_1/00001.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_1/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_1/00009.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_1/00009.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_1/00009.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_1/00009.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00000.png index 8b6d9e79..21398f44 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00003.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00003.png index 0a415f28..fe47f76c 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00003.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00003.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00005.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00005.png index 1f8bb2df..0b782048 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00005.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00005.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00006.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00006.png index 5c23bf26..de413d6b 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00006.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00006.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00008.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00008.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00008.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_ok_2/00008.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_1/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_1/00000.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_1/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_1/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_1/00001.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_1/00001.png index ab88bd3a..d885fe67 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_1/00001.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_1/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_1/00009.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_1/00009.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_1/00009.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_1/00009.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00000.png index 8b6d9e79..21398f44 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00003.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00003.png index 0a415f28..fe47f76c 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00003.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00003.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00005.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00005.png index 1f8bb2df..0b782048 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00005.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00005.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00006.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00006.png index 5c23bf26..de413d6b 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00006.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00006.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00008.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00008.png index c9222461..e90cd9db 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00008.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00008.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00009.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00009.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00009.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_expert_refused_2/00009.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_ok/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_ok/00000.png index 8b6d9e79..21398f44 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_ok/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_ok/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_ok/00001.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_ok/00001.png index 5c23bf26..de413d6b 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_ok/00001.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_ok/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_ok/00003.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_ok/00003.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_ok/00003.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_ok/00003.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00000.png index 8b6d9e79..21398f44 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00001.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00001.png index 5c23bf26..de413d6b 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00001.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00003.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00003.png index c9222461..e90cd9db 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00003.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00003.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00004.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00004.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00004.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_ascii_refused/00004.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_1/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_1/00000.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_1/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_1/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_1/00001.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_1/00001.png index ab88bd3a..d885fe67 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_1/00001.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_1/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_1/00009.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_1/00009.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_1/00009.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_1/00009.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_2/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_2/00000.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_2/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_2/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_2/00001.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_2/00001.png index ab88bd3a..d885fe67 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_2/00001.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_2/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_2/00009.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_2/00009.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_2/00009.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_2/00009.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00000.png index 8b6d9e79..21398f44 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00003.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00003.png index bad6c8e2..c6ed4629 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00003.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00003.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00004.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00004.png index 79d6436d..cd33dedb 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00004.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00004.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00005.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00005.png index 1f8bb2df..0b782048 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00005.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00005.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00007.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00007.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00007.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_ok_3/00007.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_1/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_1/00000.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_1/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_1/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_1/00001.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_1/00001.png index ab88bd3a..d885fe67 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_1/00001.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_1/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_1/00009.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_1/00009.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_1/00009.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_1/00009.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_2/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_2/00000.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_2/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_2/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_2/00001.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_2/00001.png index ab88bd3a..d885fe67 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_2/00001.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_2/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_2/00009.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_2/00009.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_2/00009.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_2/00009.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00000.png index 8b6d9e79..21398f44 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00003.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00003.png index bad6c8e2..c6ed4629 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00003.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00003.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00004.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00004.png index 79d6436d..cd33dedb 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00004.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00004.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00005.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00005.png index 1f8bb2df..0b782048 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00005.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00005.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00007.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00007.png index c9222461..e90cd9db 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00007.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00007.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00008.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00008.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00008.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_expert_refused_3/00008.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_1/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_1/00000.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_1/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_1/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_1/00001.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_1/00001.png index ab88bd3a..d885fe67 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_1/00001.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_1/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_1/00009.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_1/00009.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_1/00009.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_1/00009.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_2/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_2/00000.png index 8b6d9e79..21398f44 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_2/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_2/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_2/00001.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_2/00001.png index 79d6436d..cd33dedb 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_2/00001.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_2/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_2/00003.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_2/00003.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_2/00003.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_ok_2/00003.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_1/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_1/00000.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_1/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_1/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_1/00001.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_1/00001.png index ab88bd3a..d885fe67 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_1/00001.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_1/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_1/00009.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_1/00009.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_1/00009.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_1/00009.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00000.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00000.png index 8b6d9e79..21398f44 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00000.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00001.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00001.png index 79d6436d..cd33dedb 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00001.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00003.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00003.png index c9222461..e90cd9db 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00003.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00003.png differ diff --git a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00004.png b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00004.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00004.png and b/tests/python/snapshots/nanosp/test_ledger_sign_offchain_message_utf8_refused_2/00004.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_get_public_key_ok/00000.png b/tests/python/snapshots/nanosp/test_solana_get_public_key_ok/00000.png index c233f738..e08f5fb1 100644 Binary files a/tests/python/snapshots/nanosp/test_solana_get_public_key_ok/00000.png and b/tests/python/snapshots/nanosp/test_solana_get_public_key_ok/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_get_public_key_ok/00002.png b/tests/python/snapshots/nanosp/test_solana_get_public_key_ok/00002.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_solana_get_public_key_ok/00002.png and b/tests/python/snapshots/nanosp/test_solana_get_public_key_ok/00002.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_get_public_key_refused/00000.png b/tests/python/snapshots/nanosp/test_solana_get_public_key_refused/00000.png index c233f738..e08f5fb1 100644 Binary files a/tests/python/snapshots/nanosp/test_solana_get_public_key_refused/00000.png and b/tests/python/snapshots/nanosp/test_solana_get_public_key_refused/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_get_public_key_refused/00002.png b/tests/python/snapshots/nanosp/test_solana_get_public_key_refused/00002.png index c9222461..e90cd9db 100644 Binary files a/tests/python/snapshots/nanosp/test_solana_get_public_key_refused/00002.png and b/tests/python/snapshots/nanosp/test_solana_get_public_key_refused/00002.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_get_public_key_refused/00003.png b/tests/python/snapshots/nanosp/test_solana_get_public_key_refused/00003.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_solana_get_public_key_refused/00003.png and b/tests/python/snapshots/nanosp/test_solana_get_public_key_refused/00003.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00003.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00003.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00003.png and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00003.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00001.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00001.png index 0a1457d9..5ee5f176 100644 Binary files a/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00001.png and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00003.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00003.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00003.png and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00003.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00003.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00003.png index c9222461..e90cd9db 100644 Binary files a/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00003.png and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00003.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00004.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00004.png index 890ae49f..a3b562a7 100644 Binary files a/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00004.png and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00004.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_1/00001.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_1/00001.png index 12fdb208..68c307a6 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_1/00001.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_1/00001.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_1/00002.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_1/00002.png index 1b08a4c6..df47c275 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_1/00002.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_1/00002.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_1/00003.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_1/00003.png index 6b4fe5b6..c2f047cc 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_1/00003.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_1/00003.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_2/00005.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_2/00005.png index c1a8fd4e..1c2d6cd4 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_2/00005.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_ok_2/00005.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_refused_1/00001.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_refused_1/00001.png index 12fdb208..68c307a6 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_refused_1/00001.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_refused_1/00001.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_refused_1/00002.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_refused_1/00002.png index 1b08a4c6..df47c275 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_refused_1/00002.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_refused_1/00002.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_refused_1/00003.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_refused_1/00003.png index 6b4fe5b6..c2f047cc 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_refused_1/00003.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_expert_refused_1/00003.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_ok/00003.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_ok/00003.png index c1a8fd4e..1c2d6cd4 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_ok/00003.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_ascii_ok/00003.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_1/00001.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_1/00001.png index 12fdb208..68c307a6 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_1/00001.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_1/00001.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_1/00002.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_1/00002.png index 1b08a4c6..df47c275 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_1/00002.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_1/00002.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_1/00003.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_1/00003.png index e2f647c8..e7471c20 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_1/00003.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_1/00003.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_2/00001.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_2/00001.png index 12fdb208..68c307a6 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_2/00001.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_2/00001.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_2/00002.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_2/00002.png index e2f647c8..e7471c20 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_2/00002.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_2/00002.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_2/00003.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_2/00003.png index 04d13784..ee8e0320 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_2/00003.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_2/00003.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_3/00004.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_3/00004.png index c1a8fd4e..1c2d6cd4 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_3/00004.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_ok_3/00004.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_1/00001.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_1/00001.png index 12fdb208..68c307a6 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_1/00001.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_1/00001.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_1/00002.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_1/00002.png index 1b08a4c6..df47c275 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_1/00002.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_1/00002.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_1/00003.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_1/00003.png index e2f647c8..e7471c20 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_1/00003.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_1/00003.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_2/00001.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_2/00001.png index 12fdb208..68c307a6 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_2/00001.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_2/00001.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_2/00002.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_2/00002.png index e2f647c8..e7471c20 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_2/00002.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_2/00002.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_2/00003.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_2/00003.png index 04d13784..ee8e0320 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_2/00003.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_expert_refused_2/00003.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_1/00001.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_1/00001.png index 12fdb208..68c307a6 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_1/00001.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_1/00001.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_1/00002.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_1/00002.png index 1b08a4c6..df47c275 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_1/00002.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_1/00002.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_1/00003.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_1/00003.png index e2f647c8..e7471c20 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_1/00003.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_1/00003.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_2/00003.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_2/00003.png index c1a8fd4e..1c2d6cd4 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_2/00003.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_ok_2/00003.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_refused_1/00001.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_refused_1/00001.png index 12fdb208..68c307a6 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_refused_1/00001.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_refused_1/00001.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_refused_1/00002.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_refused_1/00002.png index 1b08a4c6..df47c275 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_refused_1/00002.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_refused_1/00002.png differ diff --git a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_refused_1/00003.png b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_refused_1/00003.png index e2f647c8..e7471c20 100644 Binary files a/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_refused_1/00003.png and b/tests/python/snapshots/stax/test_ledger_sign_offchain_message_utf8_refused_1/00003.png differ diff --git a/tests/python/snapshots/stax/test_solana_get_public_key_ok/00002.png b/tests/python/snapshots/stax/test_solana_get_public_key_ok/00002.png index f59899e9..13499fcc 100644 Binary files a/tests/python/snapshots/stax/test_solana_get_public_key_ok/00002.png and b/tests/python/snapshots/stax/test_solana_get_public_key_ok/00002.png differ diff --git a/tests/python/snapshots/stax/test_solana_simple_transfer_ok_1/00003.png b/tests/python/snapshots/stax/test_solana_simple_transfer_ok_1/00003.png index cd2f5275..a21279c8 100644 Binary files a/tests/python/snapshots/stax/test_solana_simple_transfer_ok_1/00003.png and b/tests/python/snapshots/stax/test_solana_simple_transfer_ok_1/00003.png differ diff --git a/tests/python/snapshots/stax/test_solana_simple_transfer_ok_2/00003.png b/tests/python/snapshots/stax/test_solana_simple_transfer_ok_2/00003.png index cd2f5275..a21279c8 100644 Binary files a/tests/python/snapshots/stax/test_solana_simple_transfer_ok_2/00003.png and b/tests/python/snapshots/stax/test_solana_simple_transfer_ok_2/00003.png differ