diff --git a/.github/workflows/build_and_functional_tests.yml b/.github/workflows/build_and_functional_tests.yml
new file mode 100644
index 00000000..7640e658
--- /dev/null
+++ b/.github/workflows/build_and_functional_tests.yml
@@ -0,0 +1,36 @@
+name: Build and run functional tests using ragger through reusable workflow
+
+# This workflow will build the app and then run functional tests using the Ragger framework upon Speculos emulation.
+# It calls a reusable workflow developed by Ledger's internal developer team to build the application and upload the
+# resulting binaries.
+# It then calls another reusable workflow to run the Ragger tests on the compiled application binary.
+#
+# While this workflow is optional, having functional testing on your application is mandatory and this workflow and
+# tooling environment is meant to be easy to use and adapt after forking your application
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ - develop
+ pull_request:
+ branches:
+ - main
+ - develop
+jobs:
+ build_application:
+ name: Build application using the reusable workflow
+ uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_build.yml@v1
+ with:
+ upload_app_binaries_artifact: "compiled_app_binaries"
+ run_for_devices: '["nanos", "nanox", "nanosp"]'
+
+ ragger_tests:
+ name: Run ragger tests using the reusable workflow
+ needs: build_application
+ uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_ragger_tests.yml@v1
+ with:
+ download_app_binaries_artifact: "compiled_app_binaries"
+ test_dir: tests/functional
+ run_for_devices: '["nanos", "nanox", "nanosp"]'
diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml
index 2df16d6c..d3565e6c 100644
--- a/.github/workflows/ci-workflow.yml
+++ b/.github/workflows/ci-workflow.yml
@@ -1,4 +1,4 @@
-name: Compilation & tests
+name: Compilation of build artifacts
on:
workflow_dispatch:
@@ -16,14 +16,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Parse short sha
- uses: benjlevesque/short-sha@v1.2
+ uses: benjlevesque/short-sha@v2.2
id: short-sha
with:
length: 7
outputs:
sha7: ${{ steps.short-sha.outputs.sha }}
- job_nanoS_build:
+ job_nanos_build:
name: Build for the Nano S
runs-on: ubuntu-latest
needs: prepare
@@ -33,40 +33,18 @@ jobs:
steps:
- name: Clone
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Build
run: |
make
- name: Upload app binary
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v3
with:
name: app-solar-nanos-${{ needs.prepare.outputs.sha7 }}
path: bin
- job_nanox_build:
- name: Build for the Nano X
- runs-on: ubuntu-latest
- needs: prepare
-
- container:
- image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest
-
- steps:
- - name: Clone
- uses: actions/checkout@v2
-
- - name: Build
- run: |
- make BOLOS_SDK=$NANOX_SDK
-
- - name: Upload app binary
- uses: actions/upload-artifact@v2
- with:
- name: app-solar-nanox-${{ needs.prepare.outputs.sha7 }}
- path: bin
-
job_nanosp_build:
name: Build for the Nano S Plus
runs-on: ubuntu-latest
@@ -77,81 +55,20 @@ jobs:
steps:
- name: Clone
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Build
run: |
make BOLOS_SDK=$NANOSP_SDK
- name: Upload app binary
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v3
with:
name: app-solar-nanosp-${{ needs.prepare.outputs.sha7 }}
path: bin
- job_scan_build:
- name: Clang Static Analyser
- runs-on: ubuntu-latest
- needs: job_nanos_build
-
- container:
- image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest
-
- steps:
- - uses: actions/checkout@v2
-
- - name: Build with Clang Static Analyser
- run: |
- make clean
- scan-build --use-cc=clang -analyze-headers -enable-checker security -enable-checker unix -enable-checker valist -o scan-build --status-bugs make default
- - uses: actions/upload-artifact@v2
- if: failure()
- with:
- name: scan-build
- path: scan-build
-
- job_unit_test:
- name: Unit test
- runs-on: ubuntu-latest
-
- container:
- image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest
-
- steps:
- - name: Clone
- uses: actions/checkout@v2
-
- - name: Build unit tests
- run: |
- cd tests/unit-tests/
- cmake -Bbuild -H. && make -C build && make -C build test
-
- - name: Generate code coverage
- run: |
- cd tests/unit-tests/
- lcov --directory . -b "$(realpath build/)" --capture --initial -o coverage.base && \
- lcov --rc lcov_branch_coverage=1 --directory . -b "$(realpath build/)" --capture -o coverage.capture && \
- lcov --directory . -b "$(realpath build/)" --add-tracefile coverage.base --add-tracefile coverage.capture -o coverage.info && \
- lcov --directory . -b "$(realpath build/)" --remove coverage.info '*/unit-tests/*' -o coverage.info && \
- genhtml coverage.info -o coverage
-
- - uses: actions/upload-artifact@v2
- with:
- name: code-coverage
- path: tests/unit-tests/coverage
-
- - name: Upload to codecov.io
- uses: codecov/codecov-action@v1
- with:
- token: ${{ secrets.CODECOV_TOKEN }}
- file: ./tests/unit-tests/coverage.info
- flags: unittests
- name: codecov-app-solar
- fail_ci_if_error: true
- verbose: true
-
- job_generate_doc:
- name: Generate project documentation
+ job_nanox_build:
+ name: Build for the Nano X
runs-on: ubuntu-latest
needs: prepare
@@ -160,37 +77,14 @@ jobs:
steps:
- name: Clone
- uses: actions/checkout@v2
-
- - name: HTML documentation
- run: doxygen .doxygen/Doxyfile
+ uses: actions/checkout@v3
- - uses: actions/upload-artifact@v2
- with:
- name: app-solar-docs-${{ needs.prepare.outputs.sha7 }}
- path: doc/html
-
- job_functional:
- name: Functional tests using Speculos
- runs-on: ubuntu-latest
- needs: [prepare, job_nanos_build]
-
- steps:
- - name: Clone
- uses: actions/checkout@v2
+ - name: Build
+ run: |
+ make BOLOS_SDK=$NANOX_SDK
- - name: Download app binary
- uses: actions/download-artifact@v2
+ - name: Upload app binary
+ uses: actions/upload-artifact@v3
with:
- name: app-solar-nanos-${{ needs.prepare.outputs.sha7 }}
+ name: app-solar-nanox-${{ needs.prepare.outputs.sha7 }}
path: bin
-
- - name: Install tests dependencies
- run: |
- sudo apt-get update && sudo apt-get install -y qemu-user-static
- pip install --extra-index-url https://test.pypi.org/simple/ -r tests/functional/requirements.txt
-
- - name: Run test
- env:
- CTEST_OUTPUT_ON_FAILURE: 1
- run: pytest tests/functional/ --headless
diff --git a/.github/workflows/codeql_checks.yml b/.github/workflows/codeql_checks.yml
new file mode 100644
index 00000000..3e5b455b
--- /dev/null
+++ b/.github/workflows/codeql_checks.yml
@@ -0,0 +1,46 @@
+name: "CodeQL"
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ - develop
+ pull_request:
+ branches:
+ - main
+ - develop
+ # Excluded path: add the paths you want to ignore instead of deleting the workflow
+ paths-ignore:
+ - '.github/workflows/*.yml'
+ - 'tests/*'
+
+jobs:
+ analyse:
+ name: Analyse
+ strategy:
+ matrix:
+ sdk: [ "$NANOS_SDK", "$NANOX_SDK", "$NANOSP_SDK" ]
+ #'cpp' covers C and C++
+ language: [ 'cpp' ]
+ runs-on: ubuntu-latest
+ container:
+ image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-legacy:latest
+
+ steps:
+ - name: Clone
+ uses: actions/checkout@v3
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ languages: ${{ matrix.language }}
+ queries: security-and-quality
+
+ # CodeQL will create the database during the compilation
+ - name: Build
+ run: |
+ make BOLOS_SDK=${{ matrix.sdk }}
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
diff --git a/.github/workflows/coding_style_checks.yml b/.github/workflows/coding_style_checks.yml
new file mode 100644
index 00000000..5c4cba0d
--- /dev/null
+++ b/.github/workflows/coding_style_checks.yml
@@ -0,0 +1,26 @@
+name: Run coding style check through reusable workflow
+
+# This workflow will run linting checks to ensure a level of uniformization among all Ledger applications.
+#
+# The presence of this workflow is mandatory as a minimal level of linting is required.
+# You are however free to modify the content of the .clang-format file and thus the coding style of your application.
+# We simply ask you to not diverge too much from the linting of the Boilerplate application.
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ - develop
+ pull_request:
+ branches:
+ - main
+ - develop
+jobs:
+ check_linting:
+ name: Check linting using the reusable workflow
+ uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_lint.yml@v1
+ with:
+ source: './src'
+ extensions: 'h,c'
+ version: 11
diff --git a/.github/workflows/documentation_generation.yml b/.github/workflows/documentation_generation.yml
new file mode 100644
index 00000000..bcb474c6
--- /dev/null
+++ b/.github/workflows/documentation_generation.yml
@@ -0,0 +1,31 @@
+name: Generate project documentation
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ - develop
+ pull_request:
+ branches:
+ - main
+ - develop
+
+jobs:
+ job_generate_doc:
+ name: Generate project documentation
+ runs-on: ubuntu-latest
+ container:
+ image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest
+
+ steps:
+ - name: Clone
+ uses: actions/checkout@v3
+
+ - name: HTML documentation
+ run: doxygen .doxygen/Doxyfile
+
+ - uses: actions/upload-artifact@v3
+ with:
+ name: app-solar-docs
+ path: doc/html
diff --git a/.github/workflows/guidelines_enforcer.yml b/.github/workflows/guidelines_enforcer.yml
new file mode 100644
index 00000000..bc4f213c
--- /dev/null
+++ b/.github/workflows/guidelines_enforcer.yml
@@ -0,0 +1,26 @@
+name: Ensure compliance with Ledger guidelines
+
+# This workflow is mandatory in all applications
+# It calls a reusable workflow guidelines_enforcer developed by Ledger's internal developer team.
+# The successful completion of the reusable workflow is a mandatory step for an app to be available on the Ledger
+# application store.
+#
+# More information on the guidelines can be found in the repository:
+# LedgerHQ/ledger-app-workflows/
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ - develop
+ pull_request:
+ branches:
+ - main
+ - develop
+jobs:
+ guidelines_enforcer:
+ name: Call Ledger guidelines_enforcer
+ uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_guidelines_enforcer.yml@v1
+ with:
+ run_for_devices: '["nanos", "nanosp", "nanox"]'
diff --git a/.github/workflows/lint-workflow.yml b/.github/workflows/lint-workflow.yml
deleted file mode 100644
index bbf833c3..00000000
--- a/.github/workflows/lint-workflow.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-name: Code style check
-
-on:
- workflow_dispatch:
- push:
- branches:
- - main
- pull_request:
- branches:
- - main
- - develop
-
-jobs:
- job_lint:
- name: Lint
- runs-on: ubuntu-latest
-
- steps:
- - name: Clone
- uses: actions/checkout@v2
-
- - name: Lint
- uses: DoozyX/clang-format-lint-action@v0.11
- with:
- source: './src'
- extensions: 'h,c'
- clangFormatVersion: 11
diff --git a/.github/workflows/misspellings_checks.yml b/.github/workflows/misspellings_checks.yml
new file mode 100644
index 00000000..a1ade619
--- /dev/null
+++ b/.github/workflows/misspellings_checks.yml
@@ -0,0 +1,30 @@
+name: Misspellings checks
+
+# This workflow performs some misspelling checks on the repository
+# It is there to help us maintain a level of quality in our codebase and does not have to be kept on forked
+# applications.
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ - develop
+ pull_request:
+ branches:
+ - main
+ - develop
+
+jobs:
+ misspell:
+ name: Check misspellings
+ runs-on: ubuntu-latest
+ steps:
+ - name: Clone
+ uses: actions/checkout@v3
+
+ - name: Check misspellings
+ uses: codespell-project/actions-codespell@v1
+ with:
+ builtin: clear,rare
+ check_filenames: true
diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml
new file mode 100644
index 00000000..c6a2e687
--- /dev/null
+++ b/.github/workflows/static_analysis.yml
@@ -0,0 +1,41 @@
+name: Static analysis using clang
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ - develop
+ pull_request:
+ branches:
+ - main
+ - develop
+
+jobs:
+ build_application:
+ name: Build application using the reusable workflow
+ uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_build.yml@v1
+ with:
+ upload_app_binaries_artifact: "compiled_app_binaries"
+ run_for_devices: '["nanos"]'
+
+ job_scan_build:
+ name: Clang Static Analyser
+ runs-on: ubuntu-latest
+ needs: build_application
+
+ container:
+ image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Build with Clang Static Analyser
+ run: |
+ make clean
+ scan-build --use-cc=clang -analyze-headers -enable-checker security -enable-checker unix -enable-checker valist -o scan-build --status-bugs make default
+ - uses: actions/upload-artifact@v3
+ if: failure()
+ with:
+ name: scan-build
+ path: scan-build
diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml
new file mode 100644
index 00000000..898af82c
--- /dev/null
+++ b/.github/workflows/unit_tests.yml
@@ -0,0 +1,52 @@
+name: Unit testing with Codecov coverage checking
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - main
+ - develop
+
+jobs:
+ job_unit_test:
+ name: Unit test
+ runs-on: ubuntu-latest
+
+ container:
+ image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest
+
+ steps:
+ - name: Clone
+ uses: actions/checkout@v3
+
+ - name: Build unit tests
+ run: |
+ cd tests/unit-tests/
+ cmake -Bbuild -H. && make -C build && make -C build test
+
+ - name: Generate code coverage
+ run: |
+ cd tests/unit-tests/
+ lcov --directory . -b "$(realpath build/)" --capture --initial -o coverage.base && \
+ lcov --rc lcov_branch_coverage=1 --directory . -b "$(realpath build/)" --capture -o coverage.capture && \
+ lcov --directory . -b "$(realpath build/)" --add-tracefile coverage.base --add-tracefile coverage.capture -o coverage.info && \
+ lcov --directory . -b "$(realpath build/)" --remove coverage.info '*/unit-tests/*' -o coverage.info && \
+ genhtml coverage.info -o coverage
+
+ - uses: actions/upload-artifact@v3
+ with:
+ name: code-coverage
+ path: tests/unit-tests/coverage
+
+ - name: Upload to codecov.io
+ uses: codecov/codecov-action@v3
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ file: ./tests/unit-tests/coverage.info
+ flags: unittests
+ name: codecov-app-solar
+ fail_ci_if_error: true
+ verbose: true
diff --git a/.gitignore b/.gitignore
index 2c5c7d80..b99c8b2f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,11 +2,13 @@
src/glyphs.c
src/glyphs.h
bin/
+build/
debug/
dep/
obj/
# Unit tests and code coverage
+tests/functional/snapshots-tmp/
tests/unit-tests/build/
tests/unit-tests/coverage/
tests/unit-tests/coverage.info
diff --git a/.vscode/20-ledger.ledgerblue.rules b/.vscode/20-ledger.ledgerblue.rules
new file mode 100644
index 00000000..945dd5be
--- /dev/null
+++ b/.vscode/20-ledger.ledgerblue.rules
@@ -0,0 +1 @@
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="2c97", ATTRS{idProduct}=="0006|6000|6001|6002|6003|6004|6005|6006|6007|6008|6009|600a|600b|600c|600d|600e|600f|6010|6011|6012|6013|6014|6015|6016|6017|6018|6019|601a|601b|601c|601d|601e|601f", TAG+="uaccess", TAG+="udev-acl"
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index 92693b7a..cc085518 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -24,11 +24,11 @@
"HAVE_USB_APDU",
"USB_SEGMENT_SIZE=64",
"UNUSED(x)=(void)x",
- "APPVERSION=\"1.0.0\"",
+ "APPVERSION=\"1.1.3\"",
"APPNAME=\"Solar\"",
"MAJOR_VERSION=1",
- "MINOR_VERSION=0",
- "PATCH_VERSION=0",
+ "MINOR_VERSION=1",
+ "PATCH_VERSION=3",
"IO_SEPROXYHAL_BUFFER_SIZE_B=128",
"HAVE_UX_FLOW",
"DEBUG=1",
@@ -46,4 +46,4 @@
}
],
"version": 4
-}
\ No newline at end of file
+}
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 00000000..434dec92
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,5 @@
+{
+ "recommendations": [
+ "ms-vscode.cpptools",
+ ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 0efa0424..f6fecb84 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -3,5 +3,11 @@
"*.h": "c"
},
"C_Cpp.clang_format_path": "/usr/bin/clang-format",
- "editor.formatOnSave": true
-}
\ No newline at end of file
+ "editor.formatOnSave": false,
+ "task.autoDetect": "off",
+ "python.terminal.activateEnvironment": false,
+ "buid_dir_relative_path":".",
+ "linux_udev_ledgerblue_rule_file":"20-ledger.ledgerblue.rules",
+ "docker_image": "ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest",
+ "container_name": "${workspaceFolderBasename}-container",
+}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 167e70c4..d23162fc 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -2,33 +2,54 @@
"version": "2.0.0",
"tasks": [
{
- "label": "make",
+ "label": "Run dev-tools image (on Windows with PowerShell)",
"type": "shell",
- "command": "make clean && make",
+ //Checks if a container with the name ${config:container_name} exists, and if it does, it is stopped and removed before a new container is created using the same name and other specified configuration parameters
+ "command": "if (docker ps -a --format '{{.Names}}' | Select-String -Quiet ${config:container_name}) { docker container stop ${config:container_name}; docker container rm ${config:container_name} }; docker pull ${config:docker_image}; docker run --privileged -e DISPLAY='host.docker.internal:0' -v '${workspaceFolder}:/app' -t -d --name ${config:container_name} ${config:docker_image} ",
"group": {
"kind": "build",
"isDefault": true
},
- "problemMatcher": [
- "$gcc"
- ]
+ "problemMatcher": []
},
{
- "label": "[debug] make",
+ "label": "Run dev-tools image (on macOS)",
"type": "shell",
- "command": "make clean && make DEBUG=1",
+ // Checks if a container with the name ${config:container_name} exists, and if it does, it is stopped and removed before a new container is created using the same name and other specified configuration parameters.
+ "command": "docker ps -a --format '{{.Names}}' | grep -q ${config:container_name} && (docker container stop ${config:container_name} && docker container rm ${config:container_name}) ; docker pull ${config:docker_image} && docker run --user $(id -u):$(id -g) --privileged -e DISPLAY='host.docker.internal:0' -v '/tmp/.X11-unix:/tmp/.X11-unix' -v '${workspaceFolder}:/app' -t -d --name ${config:container_name} ${config:docker_image}",
"group": {
"kind": "build",
"isDefault": true
},
- "problemMatcher": [
- "$gcc"
- ]
+ "problemMatcher": []
+ },
+ {
+ "label": "Run dev-tools image (on Linux)",
+ "type": "shell",
+ // Checks if a container with the name ${config:container_name} exists, and if it does, it is stopped and removed before a new container is created using the same name and other specified configuration parameters.
+ "command": "docker ps -a --format '{{.Names}}' | grep -q ${config:container_name} && (docker container stop ${config:container_name} && docker container rm ${config:container_name}) ; docker pull ${config:docker_image} && docker run --user $(id -u):$(id -g) --privileged -e DISPLAY=$DISPLAY -v '/dev/bus/usb:/dev/bus/usb' -v '/tmp/.X11-unix:/tmp/.X11-unix' -v '${workspaceFolder}:/app' -t -d --name ${config:container_name} ${config:docker_image}",
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ },
+ "problemMatcher": []
+ },
+ {
+ "label": "Open dev-tools container terminal",
+ "type": "shell",
+ // Opens a terminal of the dev-tools container.
+ "command": "docker exec -it ${config:container_name} bash",
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ },
+ "problemMatcher": []
},
{
- "label": "make clean",
+ "label": "Build app",
"type": "shell",
- "command": "make clean",
+ // Builds the app in release mode using the make command, inside the docker container.
+ "command": "docker exec -it ${config:container_name} bash -c 'export BOLOS_SDK=$(echo ${input:sdk}) && make -j'",
"group": {
"kind": "build",
"isDefault": true
@@ -38,9 +59,10 @@
]
},
{
- "label": "make load",
+ "label": "Build app [debug]",
"type": "shell",
- "command": "make load",
+ // Builds the app with debug mode enabled using the make command, inside the docker container.
+ "command": "docker exec -it ${config:container_name} bash -c 'export BOLOS_SDK=$(echo ${input:sdk}) && make -j DEBUG=1'",
"group": {
"kind": "build",
"isDefault": true
@@ -50,9 +72,10 @@
]
},
{
- "label": "run unit tests",
+ "label": "Clean build files",
"type": "shell",
- "command": "cd unit-tests && rm -rf build && cmake -Bbuild -H. && make -C build && CTEST_OUTPUT_ON_FAILURE=1 make -C build test",
+ // Cleans all app build files (for all device models).
+ "command": "docker exec -it ${config:container_name} bash -c 'make clean'",
"group": {
"kind": "build",
"isDefault": true
@@ -62,50 +85,161 @@
]
},
{
- "label": "run Speculos",
+ "label": "Test app with Speculos",
+ "type": "shell",
+ // Runs the app on the speculos emulator for the selected device model, in the docker container.
+ "command": "docker exec -it ${config:container_name} bash -c 'speculos --model ${input:model} build/${input:model}/bin/app.elf'",
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ },
+ "problemMatcher": []
+ },
+ {
+ "label": "Kill Speculos",
+ "type": "shell",
+ // Kills speculos emulator in the docker container.
+ "command": "docker exec -it ${config:container_name} bash -c 'pkill -f speculos'",
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ },
+ "problemMatcher": []
+ },
+ {
+ "label": "Run functional tests",
"type": "shell",
- "command": "python /path/to/speculos/speculos.py ${workspaceFolder}/bin/app.elf --ontop --sdk 1.6 --apdu-port 9999 --button-port 42000 --automation-port 43000",
+ // Runs functional tests inside the docker container (with Qt display disabled).
+ "command": "docker exec -it ${config:container_name} bash -c 'pytest tests/functional/ --tb=short -v --device ${input:model}'",
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ },
+ "problemMatcher": []
+ },
+ {
+ "label": "Run functional tests (with display)",
+ "type": "shell",
+ // Runs functional tests inside the docker container (with Qt display enabled).
+ "command": "docker exec -it ${config:container_name} bash -c 'pytest tests/functional/ --tb=short -v --device ${input:model} --display'",
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ },
+ "problemMatcher": []
+ },
+ {
+ "label": "Install tests requirements",
+ "type": "shell",
+ // Installs functional tests python requirements in the docker container.
+ "command": "docker exec -it -u 0 ${config:container_name} bash -c 'apk add gcc musl-dev python3-dev && pip install -r tests/functional/requirements.txt'",
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ },
+ "problemMatcher": []
+ },
+ {
+ "label": "Load app on device (Linux)",
+ "type": "shell",
+ // Executes make load in the container to load the app on a physical device.
+ "command": "docker exec -it ${config:container_name} bash -c 'export BOLOS_SDK=$(echo ${input:sdk}) && make load'",
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn": [
- "make debug"
+ "Install app loading requirements (Linux)"
],
"problemMatcher": []
},
{
- "label": "[debug] run Speculos",
+ "label": "Load app on device (macOS)",
"type": "shell",
- "command": "python /path/to/speculos/speculos.py -d ${workspaceFolder}/bin/app.elf --ontop --sdk 1.6 --apdu-port 9999 --button-port 42000 --automation-port 43000",
+ // Side loads the app APDU file using ledgerblue runScript.
+ "command": "source ledger/bin/activate && python3 -m ledgerblue.runScript --scp --fileName ${config:buid_dir_relative_path}/bin/app.apdu --elfFile ${config:buid_dir_relative_path}/bin/app.elf",
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn": [
- "make debug"
+ "Install app loading requirements (macOS)"
],
"problemMatcher": []
},
{
- "label": "run tests",
+ "label": "Load app on device (Windows with PowerShell)",
"type": "shell",
- "command": "cd tests && pytest",
+ // Side loads the app APDU file using ledgerblue runScript.
+ "command": "cmd.exe /C '.\\ledger\\Scripts\\activate.bat && python -m ledgerblue.runScript --scp --fileName ${config:buid_dir_relative_path}/bin/app.apdu --elfFile ${config:buid_dir_relative_path}/bin/app.elf'",
"group": {
"kind": "build",
"isDefault": true
},
+ "dependsOn": [
+ "Install app loading requirements (Windows with PowerShell)"
+ ],
"problemMatcher": []
},
+ // ------------------------------------------------------------------------------
+ // Helper tasks put in 'test' group so they are hidden from the build tasks menu.
+ // ------------------------------------------------------------------------------
{
- "label": "kill Speculos",
+ "label": "Install app loading requirements (Linux)",
"type": "shell",
- "command": "pkill -f speculos.py",
+ // Copies the ledger udev rule file to the /etc/udev/rules.d/ directory if it does not exist, then reloads the rules and triggers udev.
+ "command": "if [ ! -f '/etc/udev/rules.d/${config:linux_udev_ledgerblue_rule_file}' ]; then sudo cp .vscode/${config:linux_udev_ledgerblue_rule_file} /etc/udev/rules.d/ && sudo udevadm control --reload-rules && sudo udevadm trigger; fi",
"group": {
- "kind": "build",
+ "kind": "test",
"isDefault": true
},
"problemMatcher": []
+ },
+ {
+ "label": "Install app loading requirements (macOS)",
+ "type": "shell",
+ // Checks that virtual env is installed, otherwise installs it. Then installs ledgerblue in a virtualenv.
+ "command": "[ -n '$VIRTUAL_ENV' ] || if ! python3 -m virtualenv --version >/dev/null 2>&1; then python3 -m pip install virtualenv; fi && [ -d 'ledger' ] || python3 -m virtualenv ledger && source ledger/bin/activate && python3 -m pip show ledgerblue >/dev/null 2>&1 || python3 -m pip install ledgerblue",
+ "group": {
+ "kind": "test",
+ "isDefault": true
+ },
+ "problemMatcher": []
+ },
+ {
+ "label": "Install app loading requirements (Windows with PowerShell)",
+ "type": "shell",
+ // Checks that virtual env is installed, otherwise installs it. Then installs ledgerblue in a virtualenv.
+ "command": "cmd.exe /C 'if not exist ledger (python -m pip install virtualenv && python -m venv ledger && call ledger\\Scripts\\activate.bat && python -m pip install ledgerblue)'",
+ "group": {
+ "kind": "test",
+ "isDefault": true
+ },
+ "problemMatcher": []
+ },
+ ],
+ "inputs": [
+ {
+ "id": "sdk",
+ "type": "pickString",
+ "description": "Choose a SDK to build with",
+ "options": [
+ "$NANOS_SDK",
+ "$NANOX_SDK",
+ "$NANOSP_SDK",
+ "$STAX_SDK",
+ ]
+ },
+ {
+ "id": "model",
+ "type": "pickString",
+ "description": "Which model to run speculos for ?",
+ "options": [
+ "nanos",
+ "nanox",
+ "nanosp",
+ "stax",
+ ]
}
]
-}
\ No newline at end of file
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4ba4a0ac..eaba8d1d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,64 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [1.1.3] - 2023-08-17
+
+### Changed
+
+- Refactored deprecated throwable functions and patterns
+- Updated Ragger testing library and functional tests
+
+## [1.1.2] - 2023-08-16
+
+### Added
+
+- Merged LedgerHQ downstream commits
+- Added 'pending security review flag'
+
+## [1.1.1] - 2023-06-10
+
+### Changed
+
+- Refactored transaction display code for better readability
+- Set explicit versions for functional test dependencies
+
+### Removed
+
+- Simplified code by removing trivial switch statement
+- Removed unnecessary vote minimum check
+- Removed redundant functional test dependencies
+- Cleaned up functional tests by removing unused utilities
+
+## [1.1.0] - 2023-06-08
+
+### Added
+
+- Expanded and improved CI workflows
+- Introduced Ragger for enhanced functional testing
+
+### Changed
+
+- Refactored to align with LedgerHQ's SDKs
+- Updated app menu copyright message
+- Renamed icons to conform to LedgerHQ's naming conventions
+- Revised documentation
+- Updated Makefile to match LedgerHQ conventions
+- Updated vote terminology
+- Improved '.vscode' dev environment files
+- Updated license headers in source files
+- Enhanced unit-tests to cover recent changes
+
+### Removed
+
+- Removed HTLC transaction support
+- Removed MultiSignature Registration transaction support
+
+### Fixed
+
+- Fixed outdated Ledger dev doc links in README
+- Resolved clang static analysis failures
+- Corrected typos
+
## [1.0.0] - 2022-07-09
### Added
@@ -20,4 +78,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Updated functional and unit tests
- Refreshed documentation
-[1.0.0]: https://github.com/Solar-network/ledger-app-solar/compare/LedgerHQ:app-boilerplate:master...1.0.0
+[1.1.3]: https://github.com/Solar-network/ledger-app-solar/compare/1.1.2...1.1.3
+[1.1.2]: https://github.com/Solar-network/ledger-app-solar/compare/1.1.1...1.1.2
+[1.1.1]: https://github.com/Solar-network/ledger-app-solar/compare/1.1.0...1.1.1
+[1.1.0]: https://github.com/Solar-network/ledger-app-solar/compare/1.0.0...1.1.0
+[1.0.0]: https://github.com/Solar-network/ledger-app-solar/compare/LedgerHQ:app-boilerplate:d7c7ca843e43f7b4982b87f1ac1d7bd66045448c...1.0.0
diff --git a/Makefile b/Makefile
index e1639af6..5cf6b16c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,6 @@
# ****************************************************************************
-# This work is licensed under a Creative Commons Attribution-NoDerivatives
-# 4.0 International License.
-#
-# This software also incorporates work covered by the following copyright
-# and permission notice:
-#
# Ledger App Boilerplate
-# (c) 2020 Ledger SAS.
+# (c) Ledger SAS.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -27,117 +21,54 @@ endif
include $(BOLOS_SDK)/Makefile.defines
-APP_LOAD_PARAMS = --curve secp256k1
-ifeq ($(TARGET_NAME), TARGET_NANOX)
-APP_LOAD_PARAMS += --appFlags 0x200 # APPLICATION_FLAG_BOLOS_SETTINGS
-else
-APP_LOAD_PARAMS += --appFlags 0x000
-endif
-APP_LOAD_PARAMS += --path "44'/3333'"
-APP_LOAD_PARAMS += --path "44'/1'"
-APP_LOAD_PARAMS += $(COMMON_LOAD_PARAMS)
-
+########################################
+# Mandatory configuration #
+########################################
APP_LOAD_PARAMS += --tlvraw 9F:01
-APPNAME = "Solar"
-APPVERSION_M = 1
-APPVERSION_N = 0
-APPVERSION_P = 0
-APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)"
-
-ifeq ($(TARGET_NAME),TARGET_NANOS)
- ICONNAME=icons/nanos_app_solar.gif
-else
- ICONNAME=icons/nanox_app_solar.gif
-endif
-
-all: default
-
-DEFINES += $(DEFINES_LIB)
-DEFINES += APPNAME=\"$(APPNAME)\"
-DEFINES += APPVERSION=\"$(APPVERSION)\"
-DEFINES += MAJOR_VERSION=$(APPVERSION_M) MINOR_VERSION=$(APPVERSION_N) PATCH_VERSION=$(APPVERSION_P)
-DEFINES += OS_IO_SEPROXYHAL
-DEFINES += HAVE_BAGL HAVE_UX_FLOW HAVE_SPRINTF
-DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=6 IO_HID_EP_LENGTH=64 HAVE_USB_APDU
-DEFINES += USB_SEGMENT_SIZE=64
-DEFINES += BLE_SEGMENT_SIZE=32
-DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=0 WEBUSB_URL=""
-DEFINES += UNUSED\(x\)=\(void\)x
-DEFINES += NANO_PXLS_PER_LINE=114
+# Application name
+APPNAME = "Solar"
-ifeq ($(TARGET_NAME),TARGET_NANOX)
- DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000 HAVE_BLE_APDU
-endif
-
-ifeq ($(TARGET_NAME),TARGET_NANOS)
- DEFINES += IS_NANOS=1
- DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128
-else
- DEFINES += IS_NANOS=0
- DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300
- DEFINES += HAVE_GLO096
- DEFINES += BAGL_WIDTH=128 BAGL_HEIGHT=64
- DEFINES += HAVE_BAGL_ELLIPSIS
- DEFINES += HAVE_BAGL_FONT_OPEN_SANS_REGULAR_11PX
- DEFINES += HAVE_BAGL_FONT_OPEN_SANS_EXTRABOLD_11PX
- DEFINES += HAVE_BAGL_FONT_OPEN_SANS_LIGHT_16PX
-endif
-
-DEBUG = 0
-ifneq ($(DEBUG),0)
- DEFINES += HAVE_PRINTF
- ifeq ($(TARGET_NAME),TARGET_NANOS)
- DEFINES += PRINTF=screen_printf
- else
- DEFINES += PRINTF=mcu_usb_printf
- endif
-else
- DEFINES += PRINTF\(...\)=
-endif
-
-ifneq ($(BOLOS_ENV),)
-$(info BOLOS_ENV=$(BOLOS_ENV))
-CLANGPATH := $(BOLOS_ENV)/clang-arm-fropi/bin/
-GCCPATH := $(BOLOS_ENV)/gcc-arm-none-eabi-5_3-2016q1/bin/
-else
-$(info BOLOS_ENV is not set: falling back to CLANGPATH and GCCPATH)
-endif
-ifeq ($(CLANGPATH),)
-$(info CLANGPATH is not set: clang will be used from PATH)
-endif
-ifeq ($(GCCPATH),)
-$(info GCCPATH is not set: arm-none-eabi-* will be used from PATH)
-endif
-
-CC := $(CLANGPATH)clang
-CFLAGS += -O3 -Os
-AS := $(GCCPATH)arm-none-eabi-gcc
-LD := $(GCCPATH)arm-none-eabi-gcc
-LDFLAGS += -O3 -Os
-LDLIBS += -lm -lgcc -lc
-
-include $(BOLOS_SDK)/Makefile.glyphs
+# Application version
+APPVERSION_M = 1
+APPVERSION_N = 1
+APPVERSION_P = 3
+APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)"
+# Application source files
APP_SOURCE_PATH += src
-SDK_SOURCE_PATH += lib_stusb lib_stusb_impl lib_ux
-ifeq ($(TARGET_NAME),TARGET_NANOX)
- SDK_SOURCE_PATH += lib_blewbxx lib_blewbxx_impl
-endif
+# Application icons following guidelines:
+# https://developers.ledger.com/docs/embedded-app/design-requirements/#device-icon
+ICON_NANOS = icons/app_solar_16px.gif
+ICON_NANOX = icons/app_solar_14px.gif
+ICON_NANOSP = icons/app_solar_14px.gif
+# ICON_STAX = icons/app_boilerplate_32px.gif
+
+# Application allowed derivation curves.
+CURVE_APP_LOAD_PARAMS = secp256k1
-load: all
- python3 -m ledgerblue.loadApp $(APP_LOAD_PARAMS)
+# Application allowed derivation paths.
+PATH_APP_LOAD_PARAMS = "44'/3333'" "44'/1'"
-load-offline: all
- python3 -m ledgerblue.loadApp $(APP_LOAD_PARAMS) --offline
+# Setting to allow building variant applications
+VARIANT_PARAM = COIN
+VARIANT_VALUES = SXP
-delete:
- python3 -m ledgerblue.deleteApp $(COMMON_DELETE_PARAMS)
+# Enabling DEBUG flag will enable PRINTF and disable optimizations
+#DEBUG = 1
-include $(BOLOS_SDK)/Makefile.rules
+########################################
+# Application communication interfaces #
+########################################
+ENABLE_BLUETOOTH = 1
+#ENABLE_NFC = 1
-dep/%.d: %.c Makefile
+########################################
+# NBGL custom features #
+########################################
+#ENABLE_NBGL_QRCODE = 1
+#ENABLE_NBGL_KEYBOARD = 1
+#ENABLE_NBGL_KEYPAD = 1
-listvariants:
- @echo VARIANTS COIN SOL
+include $(BOLOS_SDK)/Makefile.standard_app
diff --git a/README.md b/README.md
index 354af000..1ded7070 100644
--- a/README.md
+++ b/README.md
@@ -8,10 +8,10 @@
## Development
-Visit the [Ledger Developer Portal](https://developers.ledger.com/docs/nano-app/start-here) to learn more about Nano app development and the development environment, or skip to the following links for specific instructions on building and loading a Nano app:
+Visit the [Ledger Developer Portal](https://developers.ledger.com/docs/embedded-app/introduction) to learn more about embedded apps and the app development environment, or visit the following links for specific instructions on building and loading an embedded app:
-- [Build the application](https://developers.ledger.com/docs/nano-app/build)
-- [Load the application](https://developers.ledger.com/docs/nano-app/load)
+- [Build the Application](https://developers.ledger.com/docs/embedded-app/build-app)
+- Load the Application: [Linux](https://developers.ledger.com/docs/embedded-app/load-linux) | [Mac](https://developers.ledger.com/docs/embedded-app/load-mac)
## Documentation
diff --git a/doc/APDU.md b/doc/APDU.md
index a650b68a..959676c4 100644
--- a/doc/APDU.md
+++ b/doc/APDU.md
@@ -12,7 +12,7 @@ Status words tend to be similar to common [APDU responses](https://www.eftlab.co
## Command APDU
| Field | Length (bytes) | Description |
-| ----- | :------------: | --------------------------------------------------------------------- |
+|-------|:--------------:|-----------------------------------------------------------------------|
| CLA | 1 | Instruction class - indicates the type of command |
| INS | 1 | Instruction code - indicates the specific command |
| P1 | 1 | Instruction parameter 1 for the command |
@@ -23,6 +23,6 @@ Status words tend to be similar to common [APDU responses](https://www.eftlab.co
## Response APDU
| Field | Length (bytes) | Description |
-| ----- | :------------: | ----------------------------------------------------------------------------- |
-| RData | variable | Reponse data (can be empty) |
+|-------|:--------------:|-------------------------------------------------------------------------------|
+| RData | variable | Response data (can be empty) |
| SW | 2 | Status word containing command processing status (e.g., `0x9000` for success) |
diff --git a/doc/COMMANDS.md b/doc/COMMANDS.md
index 12ff7a91..de8995ba 100644
--- a/doc/COMMANDS.md
+++ b/doc/COMMANDS.md
@@ -3,7 +3,7 @@
## Overview
| Command Name | INS | Description |
-| ---------------- | :----: | ------------------------------------------------------------------- |
+|------------------|:------:|---------------------------------------------------------------------|
| `GET_APP_NAME` | `0xa1` | Get the ASCII encoded application name. |
| `GET_VERSION` | `0xa2` | Get the application's version as `[MAJOR(1), MINOR(1), PATCH(1)]`. |
| `GET_PUBLIC_KEY` | `0xb1` | Get the user's PublicKey given a BIP32 path. |
@@ -18,7 +18,7 @@ The `GET_APP_NAME` instruction will return the app name, "`Solar`" as an ASCII-e
### Command
| CLA | INS | P1 | P2 | Lc | CData |
-| :----: | :----: | :----: | :----: | :----: | :--------: |
+|:------:|:------:|:------:|:------:|:------:|:----------:|
| `0xe0` | `0xa1` | `0x00` | `0x00` | `0x00` | _not used_ |
> Note that `CData` is not used and should remain empty.
@@ -28,14 +28,14 @@ The `GET_APP_NAME` instruction will return the app name, "`Solar`" as an ASCII-e
For the `GET_APP_NAME` instruction, both P1 and P2 values are not used and should be set as `0x00`.
| Parameter | Value | Description |
-| :-------: | :----: | :---------: |
+|:---------:|:------:|:-----------:|
| P1 | `0x00` | _not used_ |
| P2 | `0x00` | _not used_ |
### Response
| Response length | SW | RData |
-| :-------------: | :------: | :-----: |
+|:---------------:|:--------:|:-------:|
| 5 _(bytes)_ | `0x9000` | `Solar` |
### Example Session
@@ -53,7 +53,7 @@ The `GET_VERSION` instruction will return the Solar App's version as a byte arra
### Command
| CLA | INS | P1 | P2 | Lc | CData |
-| :----: | :----: | :----: | :----: | :----: | :--------: |
+|:------:|:------:|:------:|:------:|:------:|:----------:|
| `0xe0` | `0xa2` | `0x00` | `0x00` | `0x00` | _not used_ |
> Note that `CData` is not used and should remain empty.
@@ -63,22 +63,22 @@ The `GET_VERSION` instruction will return the Solar App's version as a byte arra
For the `GET_VERSION` instruction, both P1 and P2 values are not used and should be set as `0x00`.
| Parameter | Value | Description |
-| :-------: | :----: | :---------: |
+|:---------:|:------:|:-----------:|
| P1 | `0x00` | _not used_ |
| P2 | `0x00` | _not used_ |
### Response
| Response length | SW | RData |
-| :-------------: | :------: | :------------------------------: |
+|:---------------:|:--------:|:--------------------------------:|
| 3 _(bytes)_ | `0x9000` | `[MAJOR(1), MINOR(1), PATCH(1)]` |
### Example Session
```shell
=> e0a2000000
-<= 0100009000
- # "1 0 0", 0x9000
+<= 0101039000
+ # "1 1 3", 0x9000
```
## GET_PUBLIC_KEY
@@ -88,7 +88,7 @@ The `GET_PUBLIC_KEY` instruction will return the user's PublicKey given a deriva
### Command
| CLA | INS | P1 | P2 | Lc | CData |
-| :----: | :----: | :---------------: | :---------------: | :----: | :-------------------------------------------------------------: |
+|:------:|:------:|:-----------------:|:-----------------:|:------:|:---------------------------------------------------------------:|
| `0xe0` | `0xb1` | `0x00`
`0x01` | `0x00`
`0x01` | 1 + 4n | `[len(bip32_path)(1), bip32_path{1}(4), ..., bip32_path{n}(4)]` |
### Parameters
@@ -96,13 +96,13 @@ The `GET_PUBLIC_KEY` instruction will return the user's PublicKey given a deriva
For the `GET_PUBLIC_KEY` instruction, the P1 value is used to signify whether or not to display the user's PublicKey on the Ledger device's screen and prompt the user for approval.
| P1 |
-| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
Value | Description |
---|
`0x00` | Don't display or ask for user confirmation. |
`0x01` | Display and ask for user confirmation. |
|
For the `GET_PUBLIC_KEY` instruction, the P2 value is used to signify whether or not the HD chain code should be included in the response. _(see ['BIP-0032: Extended Keys'](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#extended-keys) for more about the chain code)._
| P2 |
-| :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Value | Description |
---|
`0x00` | Don't request the chain code. |
`0x01` | Request the chain code. |
|
### Response
@@ -110,13 +110,13 @@ For the `GET_PUBLIC_KEY` instruction, the P2 value is used to signify whether or
No Chain Code:
| Response length | SW | RData |
-| :-------------: | :------: | :------------------------------------: |
+|:---------------:|:--------:|:--------------------------------------:|
| 34 _(bytes)_ | `0x9000` | `[len(public_key)(1), public_key(33)]` |
With Chain Code:
| Response length | SW | RData |
-| :-------------: | :------: | :------------------------------------------------------------------------: |
+|:---------------:|:--------:|:--------------------------------------------------------------------------:|
| 67 _(bytes)_ | `0x9000` | `[len(public_key)(1), public_key(33), len(chain_code)(1), chain_code(32)]` |
### Example Session
@@ -134,7 +134,7 @@ The `GET_ADDRESS` instruction will return the user's Address given a derivation
### Command
| CLA | INS | P1 | P2 | Lc | CData |
-| ------ | ------ | ----------------- | ------------------------------------- | ------ | --------------------------------------------------------------- |
+|--------|--------|-------------------|---------------------------------------|--------|-----------------------------------------------------------------|
| `0xe0` | `0xb2` | `0x00`
`0x01` | `0x3F` (mainnet)
`0x1E` (testnet) | 1 + 4n | `[len(bip32_path)(1), bip32_path{1}(4), ..., bip32_path{n}(4)]` |
### Parameters
@@ -142,19 +142,19 @@ The `GET_ADDRESS` instruction will return the user's Address given a derivation
For the `GET_ADDRESS` instruction, the P1 value is used to signify whether or not to display the user's PublicKey on the Ledger device's screen and prompt the user for approval.
| P1 |
-| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Value | Description |
---|
`0x00` | Don't display or ask for user confirmation. |
`0x01` | Display and ask for user confirmation. |
|
For the `GET_ADDRESS` instruction, the P2 value is used to specify which network the Address should be created for.
| P2 |
-| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Value | Network | Prefix | Example Address |
0x3F | Mainnet | S | SNAgA2XCRZDKfm5Vu9h4KR1bZw5xn9EiC3 |
0x1E | Testnet | D | D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib |
|
### Response
| Response length | SW | RData |
-| :-------------: | :------: | :--------------------------------------: |
+|:---------------:|:--------:|:----------------------------------------:|
| 35 _(bytes)_ | `0x9000` | `[len(address)(1), base_58_address(34)]` |
### Example Session
@@ -172,7 +172,7 @@ The `SIGN_MESSAGE` instruction is used to sign an ASCII text message for a given
First Chunk:
| CLA | INS | P1 | P2 | Lc | CData |
-| :----: | :----: | :----: | :----: | :----: | :-------------------------------------------------------------: |
+|:------:|:------:|:------:|:------:|:------:|:---------------------------------------------------------------:|
| `0xe0` | `0xc1` | `0x00` | `0x80` | 1 + 4n | `[len(bip32_path)(1), bip32_path{1}(4), ..., bip32_path{n}(4)]` |
> Note that the first chunk will only contain path information in `CData`.
@@ -180,7 +180,7 @@ First Chunk:
_nth_ Chunk:
| CLA | INS | P1 | P2 | Lc | CData |
-| :----: | :----: | :------: | :-----------------------------: | :--------------------: | :--------------------: |
+|:------:|:------:|:--------:|:-------------------------------:|:----------------------:|:----------------------:|
| `0xe0` | `0xc1` | _`n...`_ | `0x80` (more)
`0x00` (last) | variable (_`1...255`_) | `[payload_data_chunk]` |
### Parameters
@@ -190,19 +190,19 @@ For the `SIGN_MESSAGE` instruction, the P1 value is used to represent the chunk'
> There is currently a limit of 8 chunks max.
| P1 |
-| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Value | Description |
---|
`0x00` | The first chunk |
`...` | _nth_ chunk |
|
For the `SIGN_MESSAGE` instruction, the P2 value is used to signify whether there are more chunks to be received or if the current chunk is the final chunk of the request session.
| P2 |
-| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Value | Description |
---|
`0x80` | More chunks should be expected. |
`0x00` | This is the final chunk that should be expected. |
|
### Response
| Response length | SW | RData |
-| :-------------: | :------: | :-----------------------: |
+|:---------------:|:--------:|:-------------------------:|
| 64 _(bytes)_ | `0x9000` | `[schnorr_signature(64)]` |
### Example Session
@@ -223,7 +223,7 @@ The `SIGN_TX` instruction is used to sign a Solar transaction for a given deriva
First Chunk:
| CLA | INS | P1 | P2 | Lc | CData |
-| :----: | :----: | :----: | :----: | :----: | :-------------------------------------------------------------: |
+|:------:|:------:|:------:|:------:|:------:|:---------------------------------------------------------------:|
| `0xe0` | `0xc2` | `0x00` | `0x80` | 1 + 4n | `[len(bip32_path)(1), bip32_path{1}(4), ..., bip32_path{n}(4)]` |
> Note that the first chunk will only contain path information in `CData`.
@@ -231,7 +231,7 @@ First Chunk:
_nth_ Chunk:
| CLA | INS | P1 | P2 | Lc | CData |
-| :----: | :----: | :------: | :-----------------------------: | :--------------------: | :--------------------: |
+|:------:|:------:|:--------:|:-------------------------------:|:----------------------:|:----------------------:|
| `0xe0` | `0xc2` | _`n...`_ | `0x80` (more)
`0x00` (last) | variable (_`1...255`_) | `[payload_data_chunk]` |
### Parameters
@@ -241,19 +241,19 @@ For the `SIGN_TX` instruction, the P1 value is used to represent the chunk's ind
> There is currently a limit of 8 chunks max.
| P1 |
-| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Value | Description |
---|
`0x00` | The first chunk |
`...` | _nth_ chunk |
|
For the `SIGN_TX` instruction, the P2 value is used to signify whether there are more chunks to be received or if the current chunk is the final chunk of the request session.
| P2 |
-| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Value | Description |
---|
`0x80` | More chunks should be expected. |
`0x00` | This is the final chunk that should be expected. |
|
### Response
| Response length | SW | RData |
-| :-------------: | :------: | :---------------: |
+|:---------------:|:--------:|:-----------------:|
| 64 _(bytes)_ | `0x9000` | `[signature(64)]` |
### Example Session
@@ -268,17 +268,17 @@ For the `SIGN_TX` instruction, the P2 value is used to signify whether there are
## Status Words
| SW | SW name | Description |
-| :------: | :--------------------------- | :----------------------------------------------- |
+|:--------:|:-----------------------------|:-------------------------------------------------|
| `0x6985` | `SW_DENY` | Rejected by user |
| `0x6A86` | `SW_WRONG_P1P2` | Either `P1` or `P2` is incorrect |
-| `0x6A87` | `SW_WRONG_DATA_LENGTH` | `Lc` or minimum APDU lenght is incorrect |
+| `0x6A87` | `SW_WRONG_DATA_LENGTH` | `Lc` or minimum APDU length is incorrect |
| `0x6D00` | `SW_INS_NOT_SUPPORTED` | No command exists with `INS` |
| `0x6E00` | `SW_CLA_NOT_SUPPORTED` | Bad `CLA` used for this application |
-| `0xB000` | `SW_WRONG_RESPONSE_LENGTH` | Wrong response lenght (buffer size problem) |
+| `0xB000` | `SW_WRONG_RESPONSE_LENGTH` | Wrong response length (buffer size problem) |
| `0xB001` | `SW_DISPLAY_BIP32_PATH_FAIL` | BIP32 path conversion to string failed |
| `0xB002` | `SW_DISPLAY_PUBLICKEY_FAIL` | PublicKey conversion to string failed |
| `0xB003` | `SW_DISPLAY_AMOUNT_FAIL` | Amount conversion to string failed |
-| `0xB004` | `SW_WRONG_TX_LENGTH` | Wrong raw transaction lenght |
+| `0xB004` | `SW_WRONG_TX_LENGTH` | Wrong raw transaction length |
| `0xB005` | `SW_TX_PARSING_FAIL` | Failed to parse raw transaction |
| `0xB006` | `SW_TX_HASH_FAIL` | Failed to compute hash digest of raw transaction |
| `0xB007` | `SW_BAD_STATE` | Security issue with bad state |
diff --git a/doc/TRANSACTION.md b/doc/TRANSACTION.md
index 28a5b051..d821e3e1 100644
--- a/doc/TRANSACTION.md
+++ b/doc/TRANSACTION.md
@@ -48,12 +48,8 @@ The network/version byte is used to set the leading character of the address and
## Transaction Structures
- TypeGroup 1
- - [Type 4: MultiSignature Registration](./transactions/TG01_T04_MULTISIGNATURE_REG.md)
- [Type 5: IPFS](./transactions/TG01_T05_IPFS.md)
- [Type 6: Transfer](./transactions/TG01_T06_TRANSFER.md)
- - [Type 8: HTLC Lock](./transactions/TG01_T08_HTLC_LOCK.md)
- - [Type 9: HTLC Claim](./transactions/TG01_T09_HTLC_CLAIM.md)
- - [Type 10: HTLC Refund](./transactions/TG01_T10_HTLC_REFUND.md)
- TypeGroup 2
- [Type 0: Burn](./transactions/TG02_T00_BURN.md)
- [Type 2: Vote](./transactions/TG02_T02_VOTE.md)
@@ -69,7 +65,5 @@ Solar transaction fees are dynamic and can be found via the network's API: [http
## Links
-- Solar API Documentation - [https://docs.solar.org/api/public-rest-api/getting-started](https://docs.solar.org/api/public-rest-api/getting-started)
-- Solar Explorer - [https://explorer.solar.org](https://explorer.solar.org)
-- Solar Staking - [https://solar.org/staking](https://solar.org/staking)
+- Solar Documentation - [https://docs.solar.org/](https://docs.solar.org)
- Solar Whitepaper - [https://docs.solar.org/assets/documents/whitepaper-february-2022.pdf](https://docs.solar.org/assets/documents/whitepaper-february-2022.pdf)
diff --git a/doc/transactions/TG01_T04_MULTISIGNATURE_REG.md b/doc/transactions/TG01_T04_MULTISIGNATURE_REG.md
deleted file mode 100644
index b957031b..00000000
--- a/doc/transactions/TG01_T04_MULTISIGNATURE_REG.md
+++ /dev/null
@@ -1,60 +0,0 @@
-# TypeGroup 1 | Type 4: MultiSignature Registration
-
-## JSON
-
-```json
-{
- "version": 3,
- "network": 63,
- "typeGroup": 1,
- "type": 4,
- "nonce": "3",
- "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
- "fee": "2000000000",
- "amount": "0",
- "asset": {
- "multiSignature": {
- "publicKeys": [
- "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
- "03df0a1eb42d99b5de395cead145ba1ec2ea837be308c7ce3a4e8018b7efc7fdb8",
- "03860d76b1df09659ac282cea3da5bd84fc45729f348a4a8e5f802186be72dc17f"
- ],
- "min": 2
- }
- }
-}
-```
-
-## Serialised
-
-```shell
-ff033f0100000004000300000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1920094357700000000000203034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19203df0a1eb42d99b5de395cead145ba1ec2ea837be308c7ce3a4e8018b7efc7fdb803860d76b1df09659ac282cea3da5bd84fc45729f348a4a8e5f802186be72dc17f
-```
-
-## Deserialised
-
-| Key | Pos. | Size
_(bytes)_ | Value
_(hex)_ |
-| :------------------- | :-------: | :---------------: | :--------------------------------------------------------------------- |
-| **Header:** | **[0]** | **1** | `0xff` |
-| **Version:** | **[1]** | **1** | `0x03` |
-| **Network:** | **[2]** | **1** | `0x3f` |
-| **Typegroup:** | **[3]** | **4** | `0x01000000` |
-| **Type:** | **[7]** | **2** | `0x0400` |
-| **Nonce:** | **[9]** | **8** | `0x0300000000000000` |
-| **SenderPublicKey:** | **[17]** | **33** | `0x034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192` |
-| **Fee:** | **[50]** | **8** | `0x0094357700000000` |
-| **Memo Length:** | **[58]** | **1** | `0x00` |
-| **Key Min:** | **[59]** | **1** | `0x02` |
-| **Key Count:** | **[60]** | **1** | `0x03` |
-| **Key 1:** | **[61]** | **33** | `0x034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192` |
-| **Key 2:** | **[94]** | **33** | `0x03df0a1eb42d99b5de395cead145ba1ec2ea837be308c7ce3a4e8018b7efc7fdb8` |
-| **Key 3:** | **[127]** | **33** | `0x03860d76b1df09659ac282cea3da5bd84fc45729f348a4a8e5f802186be72dc17f` |
-
-## APDU Session
-
-```shell
-=> e0c2008015058000002c80000d05800000000000000000000000
-<= 9000
-=> e0c20100a0ff033f0100000004000300000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1920094357700000000000203034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19203df0a1eb42d99b5de395cead145ba1ec2ea837be308c7ce3a4e8018b7efc7fdb803860d76b1df09659ac282cea3da5bd84fc45729f348a4a8e5f802186be72dc17f
-<= , 0x9000
-```
diff --git a/doc/transactions/TG01_T05_IPFS.md b/doc/transactions/TG01_T05_IPFS.md
index b0b5ca77..df074066 100644
--- a/doc/transactions/TG01_T05_IPFS.md
+++ b/doc/transactions/TG01_T05_IPFS.md
@@ -4,23 +4,23 @@
```json
{
- "version": 3,
- "network": 63,
- "typeGroup": 1,
- "type": 5,
- "nonce": "4",
- "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
- "fee": "500000000",
- "asset": {
- "ipfs": "QmYSK2JyM3RyDyB52caZCTKFR3HKniEcMnNJYdk8DQ6KKB"
- }
+ "version": 3,
+ "network": 63,
+ "typeGroup": 1,
+ "type": 5,
+ "nonce": "7",
+ "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
+ "fee": "5000000",
+ "asset": {
+ "ipfs": "QmYSK2JyM3RyDyB52caZCTKFR3HKniEcMnNJYdk8DQ6KKB"
+ }
}
```
## Serialised
```shell
-ff033f0100000005000400000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1920065cd1d000000000012209608184d6cee2b9af8e6c2a46fc9318adf73329aeb8a86cf8472829fff5bb89e
+ff033f0100000005000700000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192404b4c00000000000012209608184d6cee2b9af8e6c2a46fc9318adf73329aeb8a86cf8472829fff5bb89e
```
## Deserialised
@@ -32,9 +32,9 @@ ff033f0100000005000400000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b
| **Network:** | **[2]** | **1** | `0x3f` |
| **TypeGroup:** | **[3]** | **4** | `0x01000000` |
| **Type:** | **[7]** | **2** | `0x0500` |
-| **Nonce:** | **[9]** | **8** | `0x0400000000000000` |
+| **Nonce:** | **[9]** | **8** | `0x0700000000000000` |
| **SenderPublicKey:** | **[17]** | **33** | `0x034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192` |
-| **Fee:** | **[50]** | **8** | `0x0065cd1d00000000` |
+| **Fee:** | **[50]** | **8** | `0x404b4c0000000000` |
| **Memo Length:** | **[58]** | **1** | `0x00` |
| **IPFS Hash:** | **[59]** | **34** | `0x12209608184d6cee2b9af8e6c2a46fc9318adf73329aeb8a86cf8472829fff5bb89e` |
@@ -53,6 +53,6 @@ ff033f0100000005000400000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b
```shell
=> e0c2008015058000002c80000d05800000000000000000000000
<= 9000
-=> e0c201005dff033f0100000005000400000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1920065cd1d000000000012209608184d6cee2b9af8e6c2a46fc9318adf73329aeb8a86cf8472829fff5bb89e
+=> e0c201005dff033f0100000005000700000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192404b4c00000000000012209608184d6cee2b9af8e6c2a46fc9318adf73329aeb8a86cf8472829fff5bb89e
<= , 0x9000
```
diff --git a/doc/transactions/TG01_T06_TRANFER.md b/doc/transactions/TG01_T06_TRANFER.md
index cfe2a24d..be61d2c8 100644
--- a/doc/transactions/TG01_T06_TRANFER.md
+++ b/doc/transactions/TG01_T06_TRANFER.md
@@ -4,64 +4,65 @@
```json
{
- "version": 3,
- "network": 63,
- "type": 6,
- "nonce": "5",
- "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
- "fee": "10000000",
- "amount": "0",
- "asset": {
- "transfers": [
- { "amount": "1", "recipientId": "SNAgA2XCRZDKfm5Vu9h4KR1bZw5xn9EiC3" },
- { "amount": "1", "recipientId": "SjHT1fxVsW75eaQUPN4U2SEgFVU8ZqSVgk" },
- { "amount": "1", "recipientId": "SVzKH9r6u8UGcd2Ki7tAzQtB5Pa6FRn4GA" },
- { "amount": "1", "recipientId": "SVhLL7NR8WhkKRfYDzSmGxUH4Gg5k3uis7" },
- { "amount": "1", "recipientId": "SeznGToSzxw7maHDWXD2eRoTBSS2BmK8nU" },
- { "amount": "1", "recipientId": "SfVFPA5e2JYcgJeUmVBEsFCYCWpt5xkZ5o" },
- { "amount": "1", "recipientId": "SQEDRvC79Tqqmv85FrnqG4AxAxFoYPADCa" },
- { "amount": "1", "recipientId": "SX87pA6bJdQQf57JnUUkzVJxZ2n9jxDgeN" },
- { "amount": "1", "recipientId": "SMMJgffKfvtERv3d4MFeypAg53UcxJ9dE1" },
- { "amount": "1", "recipientId": "SefdTc8Sjx5pqSUu3TpfjFw6epyPYWoooQ" },
- { "amount": "1", "recipientId": "SSB1coESUy1GHsXjxd1Qzw5e1HqMUNQzRG" },
- { "amount": "1", "recipientId": "SNtHvv7fr23EcKHkXeSwCYz6w2ZLaT7y9y" },
- { "amount": "1", "recipientId": "SUogQH6n5EjwFnXwDapkJ1jri13Hrj1Ppz" },
- { "amount": "1", "recipientId": "SY4RAvsUTZ5q9PR9Df28vguH6LfRFrgB3a" },
- { "amount": "1", "recipientId": "SPZynxFxAtSBVKQWQW8LQPtrt87CBqpn7i" },
- { "amount": "1", "recipientId": "Sj6YjvZYDH4xh8HsRiYzWLBpeAkx65Nc1W" },
- { "amount": "1", "recipientId": "SX3XMHrMSbXLLNGcRVbMBy4WgQbS3MZzWV" },
- { "amount": "1", "recipientId": "SYqJcLu2wWYHDYvSomgsDPtnteCVhpNCTQ" },
- { "amount": "1", "recipientId": "Sa1v9xUZaniWKiCGzEV7qYXt1pW3G3XJbi" },
- { "amount": "1", "recipientId": "SQVwXdWCqouKWQhaAJMsNieZmjE3GLYYiz" },
- { "amount": "1", "recipientId": "SR1ZhBPLnSvrq3SQt8zeqBshemiudGb9fe" },
- { "amount": "1", "recipientId": "Sd1beR5X9pKKEYSxYWc7XXozC52y8QGJSt" },
- { "amount": "1", "recipientId": "SScQEYdkr5mPGD9uwFrdk15KjyKAfwHZFc" },
- { "amount": "1", "recipientId": "SRMhbyiuDa14kQKE7g8NB9jrBE8Jh9NwPv" },
- { "amount": "1", "recipientId": "SUwp9puY8x9GYbvq8X4eYE5UjQxCgmNJMJ" },
- { "amount": "1", "recipientId": "ShomZcGU7c15EUXTUAfZB2QHw17UsHxxyf" },
- { "amount": "1", "recipientId": "ScCTPEwY4Bz2cTJJxL4Fy388zRTrAKmV8m" },
- { "amount": "1", "recipientId": "ShqpcENQP4gSqRcrC1oqAzSiNscvutyQ3B" },
- { "amount": "1", "recipientId": "SjcaXuPypJxUv8qg4z7SaAry9ipqkVZsV2" },
- { "amount": "1", "recipientId": "SZk35koLSrjSetXda5toYEhNNv3GNbosDN" },
- { "amount": "1", "recipientId": "SVBBoMW8u2TiH4C59yi5wxk5mis81NJupL" },
- { "amount": "1", "recipientId": "SgZEJxkDxfDSWP38QjkDkAf9uQLwb4XL8N" },
- { "amount": "1", "recipientId": "SgE9Mqj1ZX9ziL9bJUUaRXzwNibEocJm5s" },
- { "amount": "1", "recipientId": "SYkqTvG2n54Fbg1hAiZDeK33DYwCYZWcuC" },
- { "amount": "1", "recipientId": "SjUcnukBRT6qxLRbbyrsQxVjbMdVLYRi5a" },
- { "amount": "1", "recipientId": "SNSmzTzFPmzSmaKgcDj32nz7aJp1dJqJ5a" },
- { "amount": "1", "recipientId": "SRdLAGYYk8HVeL3iJxRmYxZ9qvGUdRBiub" },
- { "amount": "1", "recipientId": "SQf1Dpta8b94FYjKDBu2dfFF4EdUfLMnoU" },
- { "amount": "1", "recipientId": "Si5KNcn97V6TZYH1ccZZpyMvCJZmKuLEzv" },
- { "amount": "1", "recipientId": "SfxX8nJVJ5rUbAXPVgFMXhpEbXXp1P3aWc" }
- ]
- }
+ "version": 3,
+ "network": 63,
+ "type": 6,
+ "nonce": "8",
+ "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
+ "fee": "50000000",
+ "amount": "0",
+ "asset": {
+ "transfers": [
+ { "amount": "1", "recipientId": "SNAgA2XCRZDKfm5Vu9h4KR1bZw5xn9EiC3" },
+ { "amount": "1", "recipientId": "SjHT1fxVsW75eaQUPN4U2SEgFVU8ZqSVgk" },
+ { "amount": "1", "recipientId": "SVzKH9r6u8UGcd2Ki7tAzQtB5Pa6FRn4GA" },
+ { "amount": "1", "recipientId": "SVhLL7NR8WhkKRfYDzSmGxUH4Gg5k3uis7" },
+ { "amount": "1", "recipientId": "SeznGToSzxw7maHDWXD2eRoTBSS2BmK8nU" },
+ { "amount": "1", "recipientId": "SfVFPA5e2JYcgJeUmVBEsFCYCWpt5xkZ5o" },
+ { "amount": "1", "recipientId": "SQEDRvC79Tqqmv85FrnqG4AxAxFoYPADCa" },
+ { "amount": "1", "recipientId": "SX87pA6bJdQQf57JnUUkzVJxZ2n9jxDgeN" },
+ { "amount": "1", "recipientId": "SMMJgffKfvtERv3d4MFeypAg53UcxJ9dE1" },
+ { "amount": "1", "recipientId": "SefdTc8Sjx5pqSUu3TpfjFw6epyPYWoooQ" },
+ { "amount": "1", "recipientId": "SSB1coESUy1GHsXjxd1Qzw5e1HqMUNQzRG" },
+ { "amount": "1", "recipientId": "SNtHvv7fr23EcKHkXeSwCYz6w2ZLaT7y9y" },
+ { "amount": "1", "recipientId": "SUogQH6n5EjwFnXwDapkJ1jri13Hrj1Ppz" },
+ { "amount": "1", "recipientId": "SY4RAvsUTZ5q9PR9Df28vguH6LfRFrgB3a" },
+ { "amount": "1", "recipientId": "SPZynxFxAtSBVKQWQW8LQPtrt87CBqpn7i" },
+ { "amount": "1", "recipientId": "Sj6YjvZYDH4xh8HsRiYzWLBpeAkx65Nc1W" },
+ { "amount": "1", "recipientId": "SX3XMHrMSbXLLNGcRVbMBy4WgQbS3MZzWV" },
+ { "amount": "1", "recipientId": "SYqJcLu2wWYHDYvSomgsDPtnteCVhpNCTQ" },
+ { "amount": "1", "recipientId": "Sa1v9xUZaniWKiCGzEV7qYXt1pW3G3XJbi" },
+ { "amount": "1", "recipientId": "SQVwXdWCqouKWQhaAJMsNieZmjE3GLYYiz" },
+ { "amount": "1", "recipientId": "SR1ZhBPLnSvrq3SQt8zeqBshemiudGb9fe" },
+ { "amount": "1", "recipientId": "Sd1beR5X9pKKEYSxYWc7XXozC52y8QGJSt" },
+ { "amount": "1", "recipientId": "SScQEYdkr5mPGD9uwFrdk15KjyKAfwHZFc" },
+ { "amount": "1", "recipientId": "SRMhbyiuDa14kQKE7g8NB9jrBE8Jh9NwPv" },
+ { "amount": "1", "recipientId": "SUwp9puY8x9GYbvq8X4eYE5UjQxCgmNJMJ" },
+ { "amount": "1", "recipientId": "ShomZcGU7c15EUXTUAfZB2QHw17UsHxxyf" },
+ { "amount": "1", "recipientId": "ScCTPEwY4Bz2cTJJxL4Fy388zRTrAKmV8m" },
+ { "amount": "1", "recipientId": "ShqpcENQP4gSqRcrC1oqAzSiNscvutyQ3B" },
+ { "amount": "1", "recipientId": "SjcaXuPypJxUv8qg4z7SaAry9ipqkVZsV2" },
+ { "amount": "1", "recipientId": "SZk35koLSrjSetXda5toYEhNNv3GNbosDN" },
+ { "amount": "1", "recipientId": "SVBBoMW8u2TiH4C59yi5wxk5mis81NJupL" },
+ { "amount": "1", "recipientId": "SgZEJxkDxfDSWP38QjkDkAf9uQLwb4XL8N" },
+ { "amount": "1", "recipientId": "SgE9Mqj1ZX9ziL9bJUUaRXzwNibEocJm5s" },
+ { "amount": "1", "recipientId": "SYkqTvG2n54Fbg1hAiZDeK33DYwCYZWcuC" },
+ { "amount": "1", "recipientId": "SjUcnukBRT6qxLRbbyrsQxVjbMdVLYRi5a" },
+ { "amount": "1", "recipientId": "SNSmzTzFPmzSmaKgcDj32nz7aJp1dJqJ5a" },
+ { "amount": "1", "recipientId": "SRdLAGYYk8HVeL3iJxRmYxZ9qvGUdRBiub" },
+ { "amount": "1", "recipientId": "SQf1Dpta8b94FYjKDBu2dfFF4EdUfLMnoU" },
+ { "amount": "1", "recipientId": "Si5KNcn97V6TZYH1ccZZpyMvCJZmKuLEzv" },
+ { "amount": "1", "recipientId": "SfxX8nJVJ5rUbAXPVgFMXhpEbXXp1P3aWc" }
+ ]
+ }
}
+
```
## Serialised
```shell
-ff033f0100000006000500000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192809698000000000000280001000000000000003f0995750207ecaf0ccf251c1265b92ad84f55366201000000000000003ff13809c4c5fb2b3967a9b40efc70843f7db462ad01000000000000003f5f60e0594115b71d5b136cf929c8504082ac199d01000000000000003f5c2aaead4ce542788406c54e1ae31f1afdb7f08101000000000000003fc2308975254751ead4df705fc76aa84116c5e34e01000000000000003fc792d1958bb950596d0e7cd0bef325062009684801000000000000003f2031100e628422b8409810fdb438e874765846ba01000000000000003f6bd2c24bded5fdfd7888a28b3c6990503699b5e801000000000000003f009ffbb10efc47ad00a0a29cc2ef6e6c83d8c6ec01000000000000003fbe9147febbfe462cdbfda8575c18dabe85db4f5b01000000000000003f358634b58d88abf4aef3a6fe264b4ad18b74e98b01000000000000003f11745fc47a9c58c4e6f5a74eb59411ac102c6a8801000000000000003f5265ceb5d6102474ea7d0f401d6e6b9f13864a0501000000000000003f7617b5f3b82f153e388b4b200abd8636fff73dd501000000000000003f18f5df4fe3108277bfa4e39071fead9d59b35b8f01000000000000003fef283e95c3fdf0e2df9ba8321407c5621f98687601000000000000003f6af453a17439c9c258c25c707aa9fc1f3b59d9b401000000000000003f7e94f3954665ebd80ced3d434c67cd4351966f2b01000000000000003f8b8ee88e27291e33ce5403ea9b159235887dcfa901000000000000003f232a71b6b2586d5b02b6a72db08759066ba2a92b01000000000000003f28c4b220f14f3745f3fff6d3c066ba2353393eb601000000000000003fac67d5bfbef4a7ed8149727b93a01e903d84ee0c01000000000000003f3a537bef2ed296a54adc354967efe3a5e52cdfb801000000000000003f2c939e4633bd96ccc1d1509dbe794299603aad9901000000000000003f53ef9af027797e4827d708d9ed47c511f4ea552401000000000000003fe103c02fc06140aeac275f8e579f3397d041f81701000000000000003fa37d6366d765f5e446fc18ddcc3da3fa300cf6bb01000000000000003fe1671fea563be042824751a3465a7dbbc482794201000000000000003ff4d63847bf07a9faad83bd69fed408b3b734dce801000000000000003f888e092eba4cbd5eab9e10646661f5a440915f9d01000000000000003f5677152f9d640b175894c8da0b9f30bad3801aff01000000000000003fd34bb692e52d515398d00fd57ce2c8bfd348055401000000000000003fcfafad73ebddc38d53317c80cdbf6d343c331d6201000000000000003f7dbca0c01f96de655cf41eb53e1b8d5e2ffa260701000000000000003ff354c71350a110a7b45b5095ed0a4601bf4bbf9d01000000000000003f0ca0fbbfb8e3f615ec4eedaef6281d4d60a8f2b201000000000000003f2f885faaf6a3fcc38b1f35c652bf72f0fd7ac60301000000000000003f24e14548f3874b9413a28f258c2b73d35ec2b2f901000000000000003fe3f48b5211d1f21034bc15908259901ecf972be801000000000000003fccbb32ea36fad927cb2c46cbc63930db6cda829d
+ff033f0100000006000500000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280f0fa020000000000280001000000000000003f0995750207ecaf0ccf251c1265b92ad84f55366201000000000000003ff13809c4c5fb2b3967a9b40efc70843f7db462ad01000000000000003f5f60e0594115b71d5b136cf929c8504082ac199d01000000000000003f5c2aaead4ce542788406c54e1ae31f1afdb7f08101000000000000003fc2308975254751ead4df705fc76aa84116c5e34e01000000000000003fc792d1958bb950596d0e7cd0bef325062009684801000000000000003f2031100e628422b8409810fdb438e874765846ba01000000000000003f6bd2c24bded5fdfd7888a28b3c6990503699b5e801000000000000003f009ffbb10efc47ad00a0a29cc2ef6e6c83d8c6ec01000000000000003fbe9147febbfe462cdbfda8575c18dabe85db4f5b01000000000000003f358634b58d88abf4aef3a6fe264b4ad18b74e98b01000000000000003f11745fc47a9c58c4e6f5a74eb59411ac102c6a8801000000000000003f5265ceb5d6102474ea7d0f401d6e6b9f13864a0501000000000000003f7617b5f3b82f153e388b4b200abd8636fff73dd501000000000000003f18f5df4fe3108277bfa4e39071fead9d59b35b8f01000000000000003fef283e95c3fdf0e2df9ba8321407c5621f98687601000000000000003f6af453a17439c9c258c25c707aa9fc1f3b59d9b401000000000000003f7e94f3954665ebd80ced3d434c67cd4351966f2b01000000000000003f8b8ee88e27291e33ce5403ea9b159235887dcfa901000000000000003f232a71b6b2586d5b02b6a72db08759066ba2a92b01000000000000003f28c4b220f14f3745f3fff6d3c066ba2353393eb601000000000000003fac67d5bfbef4a7ed8149727b93a01e903d84ee0c01000000000000003f3a537bef2ed296a54adc354967efe3a5e52cdfb801000000000000003f2c939e4633bd96ccc1d1509dbe794299603aad9901000000000000003f53ef9af027797e4827d708d9ed47c511f4ea552401000000000000003fe103c02fc06140aeac275f8e579f3397d041f81701000000000000003fa37d6366d765f5e446fc18ddcc3da3fa300cf6bb01000000000000003fe1671fea563be042824751a3465a7dbbc482794201000000000000003ff4d63847bf07a9faad83bd69fed408b3b734dce801000000000000003f888e092eba4cbd5eab9e10646661f5a440915f9d01000000000000003f5677152f9d640b175894c8da0b9f30bad3801aff01000000000000003fd34bb692e52d515398d00fd57ce2c8bfd348055401000000000000003fcfafad73ebddc38d53317c80cdbf6d343c331d6201000000000000003f7dbca0c01f96de655cf41eb53e1b8d5e2ffa260701000000000000003ff354c71350a110a7b45b5095ed0a4601bf4bbf9d01000000000000003f0ca0fbbfb8e3f615ec4eedaef6281d4d60a8f2b201000000000000003f2f885faaf6a3fcc38b1f35c652bf72f0fd7ac60301000000000000003f24e14548f3874b9413a28f258c2b73d35ec2b2f901000000000000003fe3f48b5211d1f21034bc15908259901ecf972be801000000000000003fccbb32ea36fad927cb2c46cbc63930db6cda829d
```
## Deserialised
@@ -73,9 +74,9 @@ ff033f0100000006000500000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b
| **Network:** | **[2]** | **1** | `0x3f` |
| **TypeGroup:** | **[3]** | **4** | `0x01000000` |
| **Type:** | **[7]** | **2** | `0x0600` |
-| **Nonce:** | **[9]** | **8** | `0x0500000000000000` |
+| **Nonce:** | **[9]** | **8** | `0x0800000000000000` |
| **SenderPublicKey:** | **[17]** | **33** | `0x034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192` |
-| **Fee:** | **[50]** | **8** | `0x8096980000000000` |
+| **Fee:** | **[50]** | **8** | `0x80f0fa0200000000` |
| **Memo Length:** | **[58]** | **1** | `0x00` |
| **Number of Transfers:** | **[59]** | **2** | `0x2800` |
| **Amount 1:** | **[61]** | **8** | `0x0100000000000000` |
@@ -89,7 +90,7 @@ ff033f0100000006000500000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b
```shell
=> e0c2008015058000002c80000d05800000000000000000000000
<= 9000
-=> e0c20180ffff033f0100000006000500000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192809698000000000000280001000000000000003f0995750207ecaf0ccf251c1265b92ad84f55366201000000000000003ff13809c4c5fb2b3967a9b40efc70843f7db462ad01000000000000003f5f60e0594115b71d5b136cf929c8504082ac199d01000000000000003f5c2aaead4ce542788406c54e1ae31f1afdb7f08101000000000000003fc2308975254751ead4df705fc76aa84116c5e34e01000000000000003fc792d1958bb950596d0e7cd0bef325062009684801000000000000003f2031100e628422b8409810
+=> e0c20180ffff033f0100000006000500000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280f0fa020000000000280001000000000000003f0995750207ecaf0ccf251c1265b92ad84f55366201000000000000003ff13809c4c5fb2b3967a9b40efc70843f7db462ad01000000000000003f5f60e0594115b71d5b136cf929c8504082ac199d01000000000000003f5c2aaead4ce542788406c54e1ae31f1afdb7f08101000000000000003fc2308975254751ead4df705fc76aa84116c5e34e01000000000000003fc792d1958bb950596d0e7cd0bef325062009684801000000000000003f2031100e628422b8409810
<= 9000
=> e0c20280fffdb438e874765846ba01000000000000003f6bd2c24bded5fdfd7888a28b3c6990503699b5e801000000000000003f009ffbb10efc47ad00a0a29cc2ef6e6c83d8c6ec01000000000000003fbe9147febbfe462cdbfda8575c18dabe85db4f5b01000000000000003f358634b58d88abf4aef3a6fe264b4ad18b74e98b01000000000000003f11745fc47a9c58c4e6f5a74eb59411ac102c6a8801000000000000003f5265ceb5d6102474ea7d0f401d6e6b9f13864a0501000000000000003f7617b5f3b82f153e388b4b200abd8636fff73dd501000000000000003f18f5df4fe3108277bfa4e39071fead9d59b35b8f01000000000000003fef283e95c3
<= 9000
diff --git a/doc/transactions/TG01_T08_HTLC_LOCK.md b/doc/transactions/TG01_T08_HTLC_LOCK.md
deleted file mode 100644
index 21f2e6fa..00000000
--- a/doc/transactions/TG01_T08_HTLC_LOCK.md
+++ /dev/null
@@ -1,62 +0,0 @@
-# TypeGroup 1 | Type 8: HTLC Lock
-
-## JSON
-
-```json
-{
- "version": 3,
- "network": 63,
- "typeGroup": 1,
- "type": 8,
- "nonce": "6",
- "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
- "fee": "10000000",
- "amount": "1",
- "recipientId": "SNAgA2XCRZDKfm5Vu9h4KR1bZw5xn9EiC3",
- "asset": {
- "lock": {
- "secretHash": "9c1a3815d49e0c9f78b872bfb017e825ea2db708158b70815526a830c85912b4",
- "expiration": {
- "type": 1,
- "value": 78740307
- }
- }
- }
-}
-```
-
-## Serialised
-
-```shell
-ff033f0100000008000600000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1928096980000000000000100000000000000029c1a3815d49e0c9f78b872bfb017e825ea2db708158b70815526a830c85912b401537bb1043f0995750207ecaf0ccf251c1265b92ad84f553662
-```
-
-## Deserialised
-
-| Key | Pos. | Size
_(bytes)_ | Value
_(hex)_ |
-| :---------------------- | :-------: | :---------------: | :--------------------------------------------------------------------- |
-| **Header:** | **[0]** | **1** | `0xff` |
-| **Version:** | **[1]** | **1** | `0x03` |
-| **Network:** | **[2]** | **1** | `0x3f` |
-| **Typegroup:** | **[3]** | **4** | `0x01000000` |
-| **Type:** | **[7]** | **2** | `0x0800` |
-| **Nonce:** | **[9]** | **8** | `0x0600000000000000` |
-| **SenderPublicKey:** | **[17]** | **33** | `0x034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192` |
-| **Fee:** | **[50]** | **8** | `0x8096980000000000` |
-| **Memo Length:** | **[58]** | **1** | `0x00` |
-| **Amount:** | **[59]** | **8** | `0x0100000000000000` |
-| **Secret Hash Length:** | **[67]** | **8** | `0x20` |
-| **Secret Hash:** | **[68]** | **32** | `0x9c1a3815d49e0c9f78b872bfb017e825ea2db708158b70815526a830c85912b4` |
-| **Expiration Type:** | **[100]** | **1** | `0x01` |
-| **Expiration Value:** | **[101]** | **4** | `0x537bb104` |
-| **Recipient:** | **[105]** | **21** | `0x3f0995750207ecaf0ccf251c1265b92ad84f553662` |
-
-## APDU Session
-
-```shell
-=> e0c2008015058000002c80000d05800000000000000000000000
-<= 9000
-=>
-e0c201007eff033f0100000008000600000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1928096980000000000000100000000000000209c1a3815d49e0c9f78b872bfb017e825ea2db708158b70815526a830c85912b401537bb1043f0995750207ecaf0ccf251c1265b92ad84f553662
-<= , 0x9000
-```
diff --git a/doc/transactions/TG01_T09_HTLC_CLAIM.md b/doc/transactions/TG01_T09_HTLC_CLAIM.md
deleted file mode 100644
index d1748e53..00000000
--- a/doc/transactions/TG01_T09_HTLC_CLAIM.md
+++ /dev/null
@@ -1,68 +0,0 @@
-# TypeGroup 1 | Type 9: HTLC Claim
-
-## JSON
-
-```json
-{
- "version": 3,
- "network": 63,
- "typeGroup": 1,
- "type": 9,
- "nonce": "7",
- "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
- "fee": "0",
- "asset": {
- "claim": {
- "lockTransactionId": "3aade2b98391ba7230252530cdd5124183a9f4e582660666ae873da48173ea5f",
- "unlockSecret": "c27f1ce845d8c29eebc9006be932b604fd06755521b1a8b0be4204c65377151a"
- }
- }
-}
-```
-
-## Serialised
-
-```shell
-ff033f0100000009000700000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192000000000000000000003aade2b98391ba7230252530cdd5124183a9f4e582660666ae873da48173ea5f20c27f1ce845d8c29eebc9006be932b604fd06755521b1a8b0be4204c65377151a
-```
-
-## Deserialised
-
-| Key | Pos. | Size
_(bytes)_ | Value
_(hex)_ |
-| :------------------------ | :------: | :---------------: | :--------------------------------------------------------------------- |
-| **Header:** | **[0]** | **1** | `0xff` |
-| **Version:** | **[1]** | **1** | `0x03` |
-| **Network:** | **[2]** | **1** | `0x3f` |
-| **TypeGroup:** | **[3]** | **4** | `0x01000000` |
-| **Type:** | **[7]** | **2** | `0x0900` |
-| **Nonce:** | **[9]** | **8** | `0x0700000000000000` |
-| **SenderPublicKey:** | **[17]** | **33** | `0x034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192` |
-| **Fee:** | **[50]** | **8** | `0x0000000000000000` |
-| **Memo Length:** | **[58]** | **1** | `0x00` |
-| **Hash Type:** | **[59]** | **1** | `0x00` |
-| **Lock Id:** | **[60]** | **32** | `0x3aade2b98391ba7230252530cdd5124183a9f4e582660666ae873da48173ea5f` |
-| **Unlock Secret Length:** | **[92]** | **1** | `0x20` |
-| **Unlock Secret:** | **[93]** | **32** | `0xc27f1ce845d8c29eebc9006be932b604fd06755521b1a8b0be4204c65377151a` |
-
-### Hash Types
-
-| Hash Type | Value |
-| --------- | :---: |
-| SHA256 | 0 |
-| SHA384 | 1 |
-| SHA512 | 2 |
-| SHA3256 | 3 |
-| SHA3384 | 4 |
-| SHA3512 | 5 |
-| Keccak256 | 6 |
-| Keccak384 | 7 |
-| Keccak512 | 8 |
-
-## APDU Session
-
-```shell
-=> e0c2008015058000002c80000d05800000000000000000000000
-<= 9000
-=> e0c201007dff033f0100000009000700000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192000000000000000000003aade2b98391ba7230252530cdd5124183a9f4e582660666ae873da48173ea5f20c27f1ce845d8c29eebc9006be932b604fd06755521b1a8b0be4204c65377151a
-<= , 0x9000
-```
diff --git a/doc/transactions/TG01_T10_HTLC_REFUND.md b/doc/transactions/TG01_T10_HTLC_REFUND.md
deleted file mode 100644
index 5d41444d..00000000
--- a/doc/transactions/TG01_T10_HTLC_REFUND.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# TypeGroup 1 | Type 10: HTLC Refund
-
-## JSON
-
-```json
-{
- "version": 3,
- "network": 63,
- "typeGroup": 1,
- "type": 10,
- "nonce": "8",
- "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
- "fee": "0",
- "amount": "0",
- "asset": {
- "refund": {
- "lockTransactionId": "3aade2b98391ba7230252530cdd5124183a9f4e582660666ae873da48173ea5f"
- }
- }
-}
-```
-
-## Serialised
-
-```shell
-ff033f010000000a000800000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1920000000000000000003aade2b98391ba7230252530cdd5124183a9f4e582660666ae873da48173ea5f
-```
-
-## Deserialised
-
-| Key | Pos. | Size
_(bytes)_ | Value
_(hex)_ |
-| :------------------- | :------: | :---------------: | :--------------------------------------------------------------------- |
-| **Header:** | **[0]** | **1** | `0xff` |
-| **Version:** | **[1]** | **1** | `0x03` |
-| **Network:** | **[2]** | **1** | `0x3f` |
-| **TypeGroup:** | **[3]** | **4** | `0x01000000` |
-| **Type:** | **[7]** | **2** | `0x0a00` |
-| **Nonce:** | **[9]** | **8** | `0x0800000000000000` |
-| **SenderPublicKey:** | **[17]** | **33** | `0x034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192` |
-| **Fee:** | **[50]** | **8** | `0x0000000000000000` |
-| **Memo Length:** | **[58]** | **1** | `0x00` |
-| **Lock Id:** | **[59]** | **32** | `0x3aade2b98391ba7230252530cdd5124183a9f4e582660666ae873da48173ea5f` |
-
-## APDU Session
-
-```shell
-=> e0c2008015058000002c80000d05800000000000000000000000
-<= 9000
-=> e0c201005bff033f010000000a000800000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1920000000000000000003aade2b98391ba7230252530cdd5124183a9f4e582660666ae873da48173ea5f
-<= , 0x9000
-```
diff --git a/doc/transactions/TG02_T00_BURN.md b/doc/transactions/TG02_T00_BURN.md
index 2aba9d2b..f7537448 100644
--- a/doc/transactions/TG02_T00_BURN.md
+++ b/doc/transactions/TG02_T00_BURN.md
@@ -4,22 +4,22 @@
```json
{
- "version": 3,
- "network": 63,
- "typeGroup": 2,
- "type": 0,
- "nonce": "9",
- "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
- "fee": "0",
- "burnedFee": "0",
- "amount": "100000000"
+ "version": 3,
+ "network": 63,
+ "typeGroup": 2,
+ "type": 0,
+ "nonce": "12",
+ "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
+ "fee": "0",
+ "burnedFee": "0",
+ "amount": "100000000"
}
```
## Serialised
```shell
-ff033f0200000000000900000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200000000000000000000e1f50500000000
+ff033f0200000000000c00000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200000000000000000000e1f50500000000
```
## Deserialised
@@ -31,7 +31,7 @@ ff033f0200000000000900000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b
| **Network:** | **[2]** | **1** | `0x3f` |
| **Typegroup:** | **[3]** | **4** | `0x02000000` |
| **Type:** | **[7]** | **2** | `0x0000` |
-| **Nonce:** | **[9]** | **8** | `0x0900000000000000` |
+| **Nonce:** | **[9]** | **8** | `0x0c00000000000000` |
| **SenderPublicKey:** | **[17]** | **33** | `0x034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192` |
| **Fee:** | **[50]** | **8** | `0x0000000000000000` |
| **Memo Length:** | **[58]** | **1** | `0x00` |
@@ -42,6 +42,6 @@ ff033f0200000000000900000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b
```shell
=> e0c2008015058000002c80000d05800000000000000000000000
<= 9000
-=> e0c2010043ff033f0200000000000900000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200000000000000000000e1f50500000000
+=> e0c2010043ff033f0200000000000c00000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200000000000000000000e1f50500000000
<= , 0x9000
```
diff --git a/doc/transactions/TG02_T02_VOTE.md b/doc/transactions/TG02_T02_VOTE.md
index f0411708..1421d931 100644
--- a/doc/transactions/TG02_T02_VOTE.md
+++ b/doc/transactions/TG02_T02_VOTE.md
@@ -6,27 +6,27 @@
```json
{
- "version": 3,
- "network": 63,
- "typeGroup": 2,
- "type": 2,
- "nonce": "10",
- "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
- "fee": "100000000",
- "asset": {
- "votes": {
- "gym": 50,
- "cactus1549": 25,
- "sl33p": 25
- }
- }
+ "version": 3,
+ "network": 63,
+ "typeGroup": 2,
+ "type": 2,
+ "nonce": "13",
+ "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
+ "fee": "9000000",
+ "asset": {
+ "votes": {
+ "gym": 50,
+ "cactus1549": 25,
+ "sl33p": 25
+ }
+ }
}
```
### Serialised
```shell
-ff033f0200000002000a00000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200e1f5050000000000030367796d88130a63616374757331353439c40905736c333370c409
+ff033f0200000002000d00000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192405489000000000000030367796d88130a63616374757331353439c40905736c333370c409
```
### Deserialised
@@ -38,9 +38,9 @@ ff033f0200000002000a00000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b
| **Network:** | **[2]** | **1** | `0x3f` |
| **Typegroup:** | **[3]** | **4** | `0x02000000` |
| **Type:** | **[7]** | **2** | `0x0200` |
-| **Nonce:** | **[9]** | **8** | `0x0a00000000000000` |
+| **Nonce:** | **[9]** | **8** | `0x0d00000000000000` |
| **SenderPublicKey:** | **[17]** | **33** | `0x034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192` |
-| **Fee:** | **[50]** | **8** | `0x00e1f50500000000` |
+| **Fee:** | **[50]** | **8** | `0x4054890000000000` |
| **Memo Length:** | **[58]** | **1** | `0x00` |
| **Vote Count:** | **[59]** | **1** | `0x03` |
| **Vote 1 Name Length:** | **[60]** | **1** | `0x03` |
@@ -58,7 +58,7 @@ ff033f0200000002000a00000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b
```shell
=> e0c2008015058000002c80000d05800000000000000000000000
<= 9000
-=> e0c2010057ff033f0200000002000a00000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200e1f5050000000000030367796d88130a63616374757331353439c40905736c333370c409
+=> e0c2010057ff033f0200000002000d00000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192405489000000000000030367796d88130a63616374757331353439c40905736c333370c409
<= , 0x9000
```
@@ -72,7 +72,7 @@ ff033f0200000002000a00000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b
"network": 63,
"typeGroup": 2,
"type": 2,
- "nonce": "11",
+ "nonce": "14",
"senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192",
"fee": "10000000",
"asset": {}
@@ -94,9 +94,9 @@ ff033f0200000002000b00000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b
| **Network:** | **[2]** | **1** | `0x3f` |
| **Typegroup:** | **[3]** | **4** | `0x02000000` |
| **Type:** | **[7]** | **2** | `0x0200` |
-| **Nonce:** | **[9]** | **8** | `0x0b00000000000000` |
+| **Nonce:** | **[9]** | **8** | `0x0e00000000000000` |
| **SenderPublicKey:** | **[17]** | **33** | `0x034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192` |
-| **Fee:** | **[50]** | **8** | `0x00e1f50500000000` |
+| **Fee:** | **[50]** | **8** | `0x4054890000000000` |
| **Memo Length:** | **[58]** | **1** | `0x00` |
| **Vote Count:** | **[59]** | **1** | `0x00` |
@@ -105,6 +105,6 @@ ff033f0200000002000b00000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b
```shell
=> e0c2008015058000002c80000d05800000000000000000000000
<= 9000
-=> e0c201003cff033f0200000002000b00000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200e1f505000000000000
+=> e0c201003cff033f0200000002000e00000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19240548900000000000000
<= , 0x9000
```
diff --git a/icons/nanox_app_solar.gif b/icons/app_solar_14px.gif
similarity index 100%
rename from icons/nanox_app_solar.gif
rename to icons/app_solar_14px.gif
diff --git a/icons/nanos_app_solar.gif b/icons/app_solar_16px.gif
similarity index 100%
rename from icons/nanos_app_solar.gif
rename to icons/app_solar_16px.gif
diff --git a/src/address.c b/src/address.c
index 93e1d747..0ddc9144 100644
--- a/src/address.c
+++ b/src/address.c
@@ -1,4 +1,11 @@
/*****************************************************************************
+ * Copyright (c) Solar Network
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ *****************************************************************************
+ *
* This work is licensed under a Creative Commons Attribution-NoDerivatives
* 4.0 International License.
*
@@ -6,7 +13,7 @@
* and permission notice:
*
* Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
+ * (c) Ledger SAS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,18 +28,19 @@
* limitations under the License.
*****************************************************************************/
-#include // uint*_t
-#include // size_t
+#include "address.h"
+
#include // bool
+#include // size_t
+#include // uint*_t
#include // memmove
-#include "os.h"
+#include "base58.h"
#include "cx.h"
-
-#include "address.h"
+#include "os.h"
#include "constants.h"
-#include "common/base58.h"
+#include "sw.h"
bool address_from_pubkey(const uint8_t public_key[static 33],
uint8_t *out,
@@ -45,9 +53,18 @@ bool address_from_pubkey(const uint8_t public_key[static 33],
return false;
}
- cx_ripemd160_init(&ctx);
+ if (cx_ripemd160_init_no_throw(&ctx) != CX_OK) {
+ return false;
+ }
- cx_hash((cx_hash_t *) &ctx, CX_LAST, public_key, PUBLIC_KEY_LEN, address, ADDRESS_HASH_LEN);
+ if (cx_hash_no_throw((cx_hash_t *) &ctx,
+ CX_LAST,
+ public_key,
+ PUBLIC_KEY_LEN,
+ address,
+ ADDRESS_HASH_LEN) != CX_OK) {
+ return false;
+ }
memmove(out + 1, address, ADDRESS_HASH_LEN - 1);
out[0] = network;
@@ -63,7 +80,10 @@ void crypto_get_checksum(const uint8_t *in, size_t in_len, uint8_t out[static 4]
}
int base58_encode_address(const uint8_t *in, size_t in_len, char *out, size_t out_len) {
- uint8_t tmp[in_len + 4 + 1]; // version + max_in_len + checksum + null-byte
+ if (in_len != ADDRESS_HASH_LEN) {
+ return -1;
+ }
+ uint8_t tmp[ADDRESS_HASH_LEN + 4 + 1]; // ... + checksum + null-byte
memcpy(tmp, in, in_len);
crypto_get_checksum(tmp, in_len, tmp + in_len);
diff --git a/src/address.h b/src/address.h
index eecb53e1..1e21f61d 100644
--- a/src/address.h
+++ b/src/address.h
@@ -1,31 +1,8 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
#pragma once
-#include // uint*_t
-#include // size_t
#include // bool
+#include // size_t
+#include // uint*_t
/**
* Convert public key to address.
@@ -39,7 +16,7 @@
* @param[out] out
* Pointer to output byte buffer for address.
* @param[in] out_len
- * Lenght of output byte buffer.
+ * Length of output byte buffer.
* @param[in] network
* Network byte.
*
@@ -59,7 +36,7 @@ bool address_from_pubkey(const uint8_t public_key[static 33],
* @param[in] in
* Pointer to address bytes.
* @param[in] in_len
- * Lenght of input byte buffer.
+ * Length of input byte buffer.
* @param[out] out
* Pointer to output checksum bytes.
*
@@ -73,7 +50,7 @@ void crypto_get_checksum(const uint8_t *in, size_t in_len, uint8_t out[static 4]
* @param[in] in
* Pointer to byte buffer with address.
* @param[in] in_len
- * Lenght of input address bytes.
+ * Length of input address bytes.
* @param[out] out
* Pointer to output byte buffer for address.
* @param[in] out_len
diff --git a/src/apdu/dispatcher.c b/src/apdu/dispatcher.c
index 651fad9c..fd20df87 100644
--- a/src/apdu/dispatcher.c
+++ b/src/apdu/dispatcher.c
@@ -1,4 +1,11 @@
/*****************************************************************************
+ * Copyright (c) Solar Network
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ *****************************************************************************
+ *
* This work is licensed under a Creative Commons Attribution-NoDerivatives
* 4.0 International License.
*
@@ -6,7 +13,7 @@
* and permission notice:
*
* Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
+ * (c) Ledger SAS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,20 +28,23 @@
* limitations under the License.
*****************************************************************************/
+#include "apdu/dispatcher.h"
+
#include
#include
-#include "dispatcher.h"
-#include "../constants.h"
-#include "../types.h"
-#include "../io.h"
-#include "../sw.h"
-#include "../common/buffer.h"
-#include "../handler/get_version.h"
-#include "../handler/get_app_name.h"
-#include "../handler/get_public_key.h"
-#include "../handler/get_address.h"
-#include "../handler/sign_tx.h"
+#include "buffer.h"
+#include "io.h"
+
+#include "constants.h"
+#include "sw.h"
+#include "types.h"
+
+#include "handler/get_version.h"
+#include "handler/get_app_name.h"
+#include "handler/get_public_key.h"
+#include "handler/get_address.h"
+#include "handler/sign_tx.h"
int apdu_dispatcher(const command_t *cmd) {
if (cmd->cla != CLA) {
diff --git a/src/apdu/dispatcher.h b/src/apdu/dispatcher.h
index 04d08539..f53e0db6 100644
--- a/src/apdu/dispatcher.h
+++ b/src/apdu/dispatcher.h
@@ -1,29 +1,8 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
#pragma once
-#include "../types.h"
+#include "parser.h"
+
+#include "types.h"
/**
* Parameter 2 for last APDU to receive.
diff --git a/src/apdu/parser.c b/src/apdu/parser.c
deleted file mode 100644
index 47151ad3..00000000
--- a/src/apdu/parser.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
-#include // size_t
-#include // uint*_t
-#include // bool
-
-#include "parser.h"
-#include "../types.h"
-#include "offsets.h"
-
-bool apdu_parser(command_t *cmd, uint8_t *buf, size_t buf_len) {
- // Check minimum length and Lc field of APDU command
- if (buf_len < OFFSET_CDATA || buf_len - OFFSET_CDATA != buf[OFFSET_LC]) {
- return false;
- }
-
- cmd->cla = buf[OFFSET_CLA];
- cmd->ins = (command_e) buf[OFFSET_INS];
- cmd->p1 = buf[OFFSET_P1];
- cmd->p2 = buf[OFFSET_P2];
- cmd->lc = buf[OFFSET_LC];
- cmd->data = (buf[OFFSET_LC] > 0) ? buf + OFFSET_CDATA : NULL;
-
- return true;
-}
diff --git a/src/apdu/parser.h b/src/apdu/parser.h
deleted file mode 100644
index dfba3fd6..00000000
--- a/src/apdu/parser.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-
-#include // size_t
-#include // uint*_t
-#include // bool
-
-#include "../types.h"
-
-/**
- * Parse APDU command from byte buffer.
- *
- * @param[out] cmd
- * Structured APDU command (CLA, INS, P1, P2, Lc, Command data).
- * @param[in] buf
- * Byte buffer with raw APDU command.
- * @param[in] buf_len
- * Length of byte buffer.
- *
- * @return true if success, false otherwise.
- *
- */
-bool apdu_parser(command_t *cmd, uint8_t *buf, size_t buf_len);
diff --git a/src/app_main.c b/src/app_main.c
new file mode 100644
index 00000000..cd6b9617
--- /dev/null
+++ b/src/app_main.c
@@ -0,0 +1,81 @@
+/*****************************************************************************
+ * Ledger App Boilerplate.
+ * (c) Ledger SAS.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *****************************************************************************/
+
+#include // uint*_t
+#include // memset, explicit_bzero
+
+#include "io.h"
+#include "os.h"
+#include "ux.h"
+
+#include "context.h"
+#include "globals.h"
+#include "sw.h"
+#include "types.h"
+
+#include "apdu/dispatcher.h"
+
+#include "ui/menu.h"
+
+global_ctx_t G_context;
+
+/**
+ * Handle APDU command received and send back APDU response using handlers.
+ */
+void app_main() {
+ // Length of APDU command received in G_io_apdu_buffer
+ int input_len = 0;
+ // Structured APDU command
+ command_t cmd;
+
+ io_init();
+
+ ui_menu_main();
+
+ // Reset context
+ reset_app_context();
+
+ for (;;) {
+ // Receive command bytes in G_io_apdu_buffer
+ if ((input_len = io_recv_command()) < 0) {
+ PRINTF("=> io_recv_command failure\n");
+ return;
+ }
+
+ // Parse APDU command from G_io_apdu_buffer
+ if (!apdu_parser(&cmd, G_io_apdu_buffer, input_len)) {
+ PRINTF("=> /!\\ BAD LENGTH: %.*H\n", input_len, G_io_apdu_buffer);
+ io_send_sw(SW_WRONG_DATA_LENGTH);
+ continue;
+ }
+
+ PRINTF("=> CLA=%02X | INS=%02X | P1=%02X | P2=%02X | Lc=%02X | CData=%.*H\n",
+ cmd.cla,
+ cmd.ins,
+ cmd.p1,
+ cmd.p2,
+ cmd.lc,
+ cmd.lc,
+ cmd.data);
+
+ // Dispatch structured APDU command to handler
+ if (apdu_dispatcher(&cmd) < 0) {
+ PRINTF("=> apdu_dispatcher failure\n");
+ return;
+ }
+ }
+}
diff --git a/src/common/base58.c b/src/common/base58.c
deleted file mode 100644
index 62d6d730..00000000
--- a/src/common/base58.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
-#include // size_t
-#include // uint*_t
-#include // memmove, memset
-#include // bool
-
-#include "base58.h"
-
-uint8_t const BASE58_TABLE[] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
- 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xFF, 0xFF, //
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, //
- 0x10, 0xFF, 0x11, 0x12, 0x13, 0x14, 0x15, 0xFF, 0x16, 0x17, 0x18, 0x19, //
- 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
- 0xFF, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, //
- 0xFF, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, //
- 0x37, 0x38, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF //
-};
-
-char const BASE58_ALPHABET[] = {
- '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', //
- 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', //
- 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', //
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' //
-};
-
-int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len) {
- uint8_t tmp[MAX_DEC_INPUT_SIZE] = {0};
- uint8_t buffer[MAX_DEC_INPUT_SIZE] = {0};
- uint8_t j;
- uint8_t start_at;
- uint8_t zero_count = 0;
-
- if (in_len > MAX_DEC_INPUT_SIZE || in_len < 2) {
- return -1;
- }
-
- memmove(tmp, in, in_len);
-
- for (uint8_t i = 0; i < in_len; i++) {
- if (in[i] >= sizeof(BASE58_TABLE)) {
- return -1;
- }
-
- tmp[i] = BASE58_TABLE[(int) in[i]];
-
- if (tmp[i] == 0xFF) {
- return -1;
- }
- }
-
- while ((zero_count < in_len) && (tmp[zero_count] == 0)) {
- ++zero_count;
- }
-
- j = in_len;
- start_at = zero_count;
- while (start_at < in_len) {
- uint16_t remainder = 0;
- for (uint8_t div_loop = start_at; div_loop < in_len; div_loop++) {
- uint16_t digit256 = (uint16_t)(tmp[div_loop] & 0xFF);
- uint16_t tmp_div = remainder * 58 + digit256;
- tmp[div_loop] = (uint8_t)(tmp_div / 256);
- remainder = tmp_div % 256;
- }
-
- if (tmp[start_at] == 0) {
- ++start_at;
- }
-
- buffer[--j] = (uint8_t) remainder;
- }
-
- while ((j < in_len) && (buffer[j] == 0)) {
- ++j;
- }
-
- int length = in_len - (j - zero_count);
-
- if ((int) out_len < length) {
- return -1;
- }
-
- memmove(out, buffer + j - zero_count, length);
-
- return length;
-}
-
-int base58_encode(const uint8_t *in, size_t in_len, char *out, size_t out_len) {
- uint8_t buffer[MAX_ENC_INPUT_SIZE * 138 / 100 + 1] = {0};
- size_t i, j;
- size_t stop_at;
- size_t zero_count = 0;
- size_t output_size;
-
- if (in_len > MAX_ENC_INPUT_SIZE) {
- return -1;
- }
-
- while ((zero_count < in_len) && (in[zero_count] == 0)) {
- ++zero_count;
- }
-
- output_size = (in_len - zero_count) * 138 / 100 + 1;
- stop_at = output_size - 1;
- for (size_t start_at = zero_count; start_at < in_len; start_at++) {
- int carry = in[start_at];
- for (j = output_size - 1; (int) j >= 0; j--) {
- carry += 256 * buffer[j];
- buffer[j] = carry % 58;
- carry /= 58;
-
- if (j <= stop_at - 1 && carry == 0) {
- break;
- }
- }
- stop_at = j;
- }
-
- j = 0;
- while (j < output_size && buffer[j] == 0) {
- j += 1;
- }
-
- if (out_len < zero_count + output_size - j) {
- return -1;
- }
-
- memset(out, BASE58_ALPHABET[0], zero_count);
-
- i = zero_count;
- while (j < output_size) {
- out[i++] = BASE58_ALPHABET[buffer[j++]];
- }
-
- return i;
-}
diff --git a/src/common/base58.h b/src/common/base58.h
deleted file mode 100644
index f214afd8..00000000
--- a/src/common/base58.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#pragma once
-
-#include // size_t
-#include // uint*_t
-#include // bool
-
-/**
- * Maximum length of input when decoding in base 58.
- */
-#define MAX_DEC_INPUT_SIZE 164
-/**
- * Maximum length of input when encoding in base 58.
- */
-#define MAX_ENC_INPUT_SIZE 120
-
-/**
- * Decode input string in base 58.
- *
- * @see https://tools.ietf.org/html/draft-msporny-base58-02
- *
- * @param[in] in
- * Pointer to input string buffer.
- * @param[in] in_len
- * Length of the input string buffer.
- * @param[out] out
- * Pointer to output byte buffer.
- * @param[in] out_len
- * Maximum length to write in output byte buffer.
- *
- * @return number of bytes decoded, -1 otherwise.
- *
- */
-int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len);
-
-/**
- * Encode input bytes in base 58.
- *
- * @see https://tools.ietf.org/html/draft-msporny-base58-02
- *
- * @param[in] in
- * Pointer to input byte buffer.
- * @param[in] in_len
- * Length of the input byte buffer.
- * @param[out] out
- * Pointer to output string buffer.
- * @param[in] out_len
- * Maximum length to write in output byte buffer.
- *
- * @return number of bytes encoded, -1 otherwise.
- *
- */
-int base58_encode(const uint8_t *in, size_t in_len, char *out, size_t out_len);
diff --git a/src/common/bip32.c b/src/common/bip32.c
deleted file mode 100644
index a6ac6e59..00000000
--- a/src/common/bip32.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*****************************************************************************
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
-#include // snprintf
-#include // memset, strlen
-#include // size_t
-#include // uint*_t
-#include // bool
-
-#include "bip32.h"
-#include "read.h"
-
-bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len) {
- if (out_len == 0 || out_len > MAX_BIP32_PATH) {
- return false;
- }
-
- size_t offset = 0;
-
- for (size_t i = 0; i < out_len; i++) {
- if (offset > in_len) {
- return false;
- }
- out[i] = read_u32_be(in, offset);
- offset += 4;
- }
-
- return true;
-}
-
-bool bip32_path_format(const uint32_t *bip32_path,
- size_t bip32_path_len,
- char *out,
- size_t out_len) {
- if (bip32_path_len == 0 || bip32_path_len > MAX_BIP32_PATH) {
- return false;
- }
-
- size_t offset = 0;
-
- for (uint16_t i = 0; i < bip32_path_len; i++) {
- size_t written;
-
- snprintf(out + offset, out_len - offset, "%d", bip32_path[i] & 0x7FFFFFFFu);
- written = strlen(out + offset);
- if (written == 0 || written >= out_len - offset) {
- memset(out, 0, out_len);
- return false;
- }
- offset += written;
-
- if ((bip32_path[i] & 0x80000000u) != 0) {
- snprintf(out + offset, out_len - offset, "'");
- written = strlen(out + offset);
- if (written == 0 || written >= out_len - offset) {
- memset(out, 0, out_len);
- return false;
- }
- offset += written;
- }
-
- if (i != bip32_path_len - 1) {
- snprintf(out + offset, out_len - offset, "/");
- written = strlen(out + offset);
- if (written == 0 || written >= out_len - offset) {
- memset(out, 0, out_len);
- return false;
- }
- offset += written;
- }
- }
-
- return true;
-}
diff --git a/src/common/bip32.h b/src/common/bip32.h
deleted file mode 100644
index 3e2491e1..00000000
--- a/src/common/bip32.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#pragma once
-
-#include // size_t
-#include // uint*_t
-#include // bool
-
-/**
- * Maximum length of BIP32 path allowed.
- */
-#define MAX_BIP32_PATH 10
-
-/**
- * Read BIP32 path from byte buffer.
- *
- * @param[in] in
- * Pointer to input byte buffer.
- * @param[in] in_len
- * Length of input byte buffer.
- * @param[out] out
- * Pointer to output 32-bit integer buffer.
- * @param[in] out_len
- * Number of BIP32 paths read in the output buffer.
- *
- * @return true if success, false otherwise.
- *
- */
-bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len);
-
-/**
- * Format BIP32 path as string.
- *
- * @param[in] bip32_path
- * Pointer to 32-bit integer input buffer.
- * @param[in] bip32_path_len
- * Maximum number of BIP32 paths in the input buffer.
- * @param[out] out string
- * Pointer to output string.
- * @param[in] out_len
- * Length of the output string.
- *
- * @return true if success, false otherwise.
- *
- */
-bool bip32_path_format(const uint32_t *bip32_path,
- size_t bip32_path_len,
- char *out,
- size_t out_len);
diff --git a/src/common/buffer.c b/src/common/buffer.c
deleted file mode 100644
index 3bd617bd..00000000
--- a/src/common/buffer.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*****************************************************************************
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
-#include // uint*_t
-#include // size_t
-#include // bool
-#include // memmove
-
-#include "buffer.h"
-#include "read.h"
-#include "varint.h"
-#include "bip32.h"
-
-bool buffer_can_read(const buffer_t *buffer, size_t n) {
- return buffer->size - buffer->offset >= n;
-}
-
-bool buffer_seek_set(buffer_t *buffer, size_t offset) {
- if (offset > buffer->size) {
- return false;
- }
-
- buffer->offset = offset;
-
- return true;
-}
-
-bool buffer_seek_cur(buffer_t *buffer, size_t offset) {
- if (buffer->offset + offset < buffer->offset || // overflow
- buffer->offset + offset > buffer->size) { // exceed buffer size
- return false;
- }
-
- buffer->offset += offset;
-
- return true;
-}
-
-bool buffer_seek_end(buffer_t *buffer, size_t offset) {
- if (offset > buffer->size) {
- return false;
- }
-
- buffer->offset = buffer->size - offset;
-
- return true;
-}
-
-bool buffer_read_u8(buffer_t *buffer, uint8_t *value) {
- if (!buffer_can_read(buffer, 1)) {
- *value = 0;
-
- return false;
- }
-
- *value = buffer->ptr[buffer->offset];
- buffer_seek_cur(buffer, 1);
-
- return true;
-}
-
-bool buffer_read_u16(buffer_t *buffer, uint16_t *value, endianness_t endianness) {
- if (!buffer_can_read(buffer, 2)) {
- *value = 0;
-
- return false;
- }
-
- *value = ((endianness == BE) ? read_u16_be(buffer->ptr, buffer->offset)
- : read_u16_le(buffer->ptr, buffer->offset));
-
- buffer_seek_cur(buffer, 2);
-
- return true;
-}
-
-bool buffer_read_u32(buffer_t *buffer, uint32_t *value, endianness_t endianness) {
- if (!buffer_can_read(buffer, 4)) {
- *value = 0;
-
- return false;
- }
-
- *value = ((endianness == BE) ? read_u32_be(buffer->ptr, buffer->offset)
- : read_u32_le(buffer->ptr, buffer->offset));
-
- buffer_seek_cur(buffer, 4);
-
- return true;
-}
-
-bool buffer_read_u64(buffer_t *buffer, uint64_t *value, endianness_t endianness) {
- if (!buffer_can_read(buffer, 8)) {
- *value = 0;
-
- return false;
- }
-
- *value = ((endianness == BE) ? read_u64_be(buffer->ptr, buffer->offset)
- : read_u64_le(buffer->ptr, buffer->offset));
-
- buffer_seek_cur(buffer, 8);
-
- return true;
-}
-
-bool buffer_read_varint(buffer_t *buffer, uint64_t *value) {
- int length = varint_read(buffer->ptr + buffer->offset, buffer->size - buffer->offset, value);
-
- if (length < 0) {
- *value = 0;
-
- return false;
- }
-
- buffer_seek_cur(buffer, (size_t) length);
-
- return true;
-}
-
-bool buffer_read_bip32_path(buffer_t *buffer, uint32_t *out, size_t out_len) {
- if (!bip32_path_read(buffer->ptr + buffer->offset,
- buffer->size - buffer->offset,
- out,
- out_len)) {
- return false;
- }
-
- buffer_seek_cur(buffer, sizeof(*out) * out_len);
-
- return true;
-}
-
-bool buffer_copy(const buffer_t *buffer, uint8_t *out, size_t out_len) {
- if (buffer->size - buffer->offset > out_len) {
- return false;
- }
-
- memmove(out, buffer->ptr + buffer->offset, buffer->size - buffer->offset);
-
- return true;
-}
-
-bool buffer_move(buffer_t *buffer, uint8_t *out, size_t out_len) {
- if (!buffer_copy(buffer, out, out_len)) {
- return false;
- }
-
- buffer_seek_cur(buffer, out_len);
-
- return true;
-}
diff --git a/src/common/buffer.h b/src/common/buffer.h
deleted file mode 100644
index ae3e8293..00000000
--- a/src/common/buffer.h
+++ /dev/null
@@ -1,192 +0,0 @@
-#pragma once
-
-#include // uint*_t
-#include // size_t
-#include // bool
-
-/**
- * Enumeration for endianness.
- */
-typedef enum {
- BE, /// Big Endian
- LE /// Little Endian
-} endianness_t;
-
-/**
- * Struct for buffer with size and offset.
- */
-typedef struct {
- const uint8_t *ptr; /// Pointer to byte buffer
- size_t size; /// Size of byte buffer
- size_t offset; /// Offset in byte buffer
-} buffer_t;
-
-/**
- * Tell whether buffer can read bytes or not.
- *
- * @param[in] buffer
- * Pointer to input buffer struct.
- * @param[in] n
- * Number of bytes to read in buffer.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_can_read(const buffer_t *buffer, size_t n);
-
-/**
- * Seek the buffer to specific offset.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[in] offset
- * Specific offset to seek.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_seek_set(buffer_t *buffer, size_t offset);
-
-/**
- * Seek buffer relatively to current offset.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[in] offset
- * Offset to seek relatively to `buffer->offset`.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_seek_cur(buffer_t *buffer, size_t offset);
-
-/**
- * Seek the buffer relatively to the end.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[in] offset
- * Offset to seek relatively to `buffer->size`.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_seek_end(buffer_t *buffer, size_t offset);
-
-/**
- * Read 1 byte from buffer into uint8_t.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[out] value
- * Pointer to 8-bit unsigned integer read from buffer.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_read_u8(buffer_t *buffer, uint8_t *value);
-
-/**
- * Read 2 bytes from buffer into uint16_t.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[out] value
- * Pointer to 16-bit unsigned integer read from buffer.
- * @param[in] endianness
- * Either BE (Big Endian) or LE (Little Endian).
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_read_u16(buffer_t *buffer, uint16_t *value, endianness_t endianness);
-
-/**
- * Read 4 bytes from buffer into uint32_t.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[out] value
- * Pointer to 32-bit unsigned integer read from buffer.
- * @param[in] endianness
- * Either BE (Big Endian) or LE (Little Endian).
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_read_u32(buffer_t *buffer, uint32_t *value, endianness_t endianness);
-
-/**
- * Read 8 bytes from buffer into uint64_t.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[out] value
- * Pointer to 64-bit unsigned integer read from buffer.
- * @param[in] endianness
- * Either BE (Big Endian) or LE (Little Endian).
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_read_u64(buffer_t *buffer, uint64_t *value, endianness_t endianness);
-
-/**
- * Read Bitcoin-like varint from buffer into uint64_t.
- *
- * @see https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[out] value
- * Pointer to 64-bit unsigned integer read from buffer.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_read_varint(buffer_t *buffer, uint64_t *value);
-
-/**
- * Read BIP32 path from buffer.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[out] out
- * Pointer to output 32-bit integer buffer.
- * @param[in] out_len
- * Number of BIP32 paths read in the output buffer.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_read_bip32_path(buffer_t *buffer, uint32_t *out, size_t out_len);
-
-/**
- * Copy bytes from buffer without moving offset.
- *
- * @param[in] buffer
- * Pointer to input buffer struct.
- * @param[out] out
- * Pointer to output byte buffer.
- * @param[in] out_len
- * Length of output byte buffer.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_copy(const buffer_t *buffer, uint8_t *out, size_t out_len);
-
-/**
- * Move bytes from buffer.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[out] out
- * Pointer to output byte buffer.
- * @param[in] out_len
- * Length of output byte buffer.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_move(buffer_t *buffer, uint8_t *out, size_t out_len);
diff --git a/src/common/format.c b/src/common/format.c
deleted file mode 100644
index e76a39fb..00000000
--- a/src/common/format.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
-#include // size_t
-#include // int*_t, uint*_t
-#include // strncpy, memmove
-#include // bool
-#include // snprintf
-
-#include "format.h"
-
-bool format_i64(char *dst, size_t dst_len, const int64_t value) {
- char temp[] = "-9223372036854775808";
-
- char *ptr = temp;
- int64_t num = value;
- int sign = 1;
-
- if (value < 0) {
- sign = -1;
- }
-
- while (num != 0) {
- *ptr++ = '0' + (num % 10) * sign;
- num /= 10;
- }
-
- if (value < 0) {
- *ptr++ = '-';
- } else if (value == 0) {
- *ptr++ = '0';
- }
-
- int distance = (ptr - temp) + 1;
-
- if ((int) dst_len < distance) {
- return false;
- }
-
- size_t index = 0;
-
- while (--ptr >= temp) {
- dst[index++] = *ptr;
- }
-
- dst[index] = '\0';
-
- return true;
-}
-
-bool format_u64(char *out, size_t outLen, uint64_t in) {
- uint8_t i = 0;
-
- if (outLen == 0) {
- return false;
- }
- outLen--;
-
- while (in > 9) {
- out[i] = in % 10 + '0';
- in /= 10;
- i++;
- if (i + 1 > outLen) {
- return false;
- }
- }
- out[i] = in + '0';
- out[i + 1] = '\0';
-
- uint8_t j = 0;
- char tmp;
-
- // revert the string
- while (j < i) {
- // swap out[j] and out[i]
- tmp = out[j];
- out[j] = out[i];
- out[i] = tmp;
-
- i--;
- j++;
- }
- return true;
-}
-
-bool format_fpu64(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals) {
- char buffer[21] = {0};
-
- if (!format_u64(buffer, sizeof(buffer), value)) {
- return false;
- }
-
- size_t digits = strlen(buffer);
-
- if (digits <= decimals) {
- if (dst_len <= 2 + decimals + 1) {
- return false;
- }
- *dst++ = '0';
- *dst++ = '.';
- for (uint16_t i = 0; i < decimals - digits; i++, dst++) {
- *dst = '0';
- }
- dst_len -= 2 + decimals - digits;
- strncpy(dst, buffer, dst_len);
- } else {
- if (dst_len <= digits + 1) {
- return false;
- }
-
- const size_t shift = digits - decimals;
- memmove(dst, buffer, shift);
- dst[shift] = '.';
- strncpy(dst + shift + 1, buffer + shift, decimals);
- }
-
- return true;
-}
-
-/**
- * Remove trailing zeros up to the decimal + padding.
- *
- */
-static void unpad_amount(char *amount, size_t len, size_t padding) {
- char *ptr = amount + len - 1;
- while (*ptr == '0' && *(ptr - padding) != '.') {
- *ptr-- = 0;
- }
-}
-
-#if (IS_NANOS) // Estimate amount/fee line pixel count for the Nano S.
-
-// extern from:
-// https://github.com/LedgerHQ/nanos-secure-sdk/blob/master/lib_ux/src/ux_layout_paging_compute.c#L20-#L117
-extern const char nanos_characters_width[96];
-
-// adapted from:
-// https://github.com/LedgerHQ/nanos-secure-sdk/blob/master/lib_ux/src/ux_layout_paging_compute.c#L147-#L175
-static uint32_t get_pixels(const char *text, uint8_t text_length) {
- char current_char;
- uint32_t line_width = 0;
-
- while (text_length--) {
- current_char = *text;
- line_width += (nanos_characters_width[current_char - 0x20] >> 0x04) & 0x0F;
- text++;
- }
-
- return line_width;
-}
-
-#define PXLS(num_str) (get_pixels((num_str), strlen((num_str))))
-#else // if NOT NANOS
-#define PXLS(num_str) (0)
-#endif
-
-/**
- * Determine if a new page should be used for ticker display on the Nano S.
- *
- * (e.g., avoid `123456789012345678 / 9.00 SXP` being misread as `9.00 SXP`)
- *
- */
-#define TICKER_SPACING(num_str) (IS_NANOS && PXLS((num_str)) >= NANO_PXLS_PER_LINE - 1 ? '\n' : ' ')
-
-bool format_amount(char *dst,
- size_t dst_len,
- const uint64_t value,
- uint8_t decimals,
- const char *ticker,
- size_t ticker_len) {
- char amount[22] = {0};
- if (dst_len < 22 + 5 || ticker_len > 5) {
- return false;
- }
- if (!format_fpu64(amount, 22, value, decimals)) {
- return false;
- }
-
- unpad_amount(amount, strlen(amount), 2);
-
- snprintf(dst, dst_len, "%s%c%s", amount, TICKER_SPACING(amount), ticker);
- return true;
-}
-
-bool format_percentage(char *dst, size_t dst_len, const uint16_t value, uint8_t decimals) {
- char amount[22] = {0};
- if (dst_len < 9) {
- return false;
- }
- if (!format_fpu64(amount, 22, (const uint64_t) value, decimals)) {
- return false;
- }
- snprintf(dst, dst_len, "%s%%", amount);
- return true;
-}
-
-int format_hex(const uint8_t *in, size_t in_len, char *out, size_t out_len) {
- if (out_len < 2 * in_len + 1) {
- return -1;
- }
-
- const char hex[] = "0123456789abcdef";
- size_t i = 0;
- int written = 0;
-
- while (i < in_len && (i * 2 + (2 + 1)) <= out_len) {
- uint8_t high_nibble = (in[i] & 0xF0) >> 4;
- *out = hex[high_nibble];
- out++;
-
- uint8_t low_nibble = in[i] & 0x0F;
- *out = hex[low_nibble];
- out++;
-
- i++;
- written += 2;
- }
-
- *out = '\0';
-
- return written + 1;
-}
diff --git a/src/common/format.h b/src/common/format.h
deleted file mode 100644
index d553ac51..00000000
--- a/src/common/format.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
-#pragma once
-
-#include // size_t
-#include // int*_t, uint*_t
-#include // bool
-
-/**
- * Format 64-bit signed integer as string.
- *
- * @param[out] dst
- * Pointer to output string.
- * @param[in] dst_len
- * Length of output string.
- * @param[in] value
- * 64-bit signed integer to format.
- *
- * @return true if success, false otherwise.
- *
- */
-bool format_i64(char *dst, size_t dst_len, const int64_t value);
-
-/**
- * Format 64-bit unsigned integer as string.
- *
- * @param[out] dst
- * Pointer to output string.
- * @param[in] dst_len
- * Length of output string.
- * @param[in] value
- * 64-bit unsigned integer to format.
- *
- * @return true if success, false otherwise.
- *
- */
-bool format_u64(char *dst, size_t dst_len, uint64_t value);
-
-/**
- * Format 64-bit unsigned integer as string with decimals.
- *
- * @param[out] dst
- * Pointer to output string.
- * @param[in] dst_len
- * Length of output string.
- * @param[in] value
- * 64-bit unsigned integer to format.
- * @param[in] decimals
- * Number of digits after decimal separator.
- *
- * @return true if success, false otherwise.
- *
- */
-bool format_fpu64(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals);
-
-/**
- * Format 64-bit unsigned integer as string with decimals and ticker.
- *
- * @param[out] dst
- * Pointer to output string.
- * @param[in] dst_len
- * Length of output string.
- * @param[in] value
- * 64-bit unsigned integer to format.
- * @param[in] decimals
- * Number of digits after decimal separator.
- * @param[in] ticker
- * The token's ticker name to be displayed.
- * @param[in] ticker_len
- * The length of the ticker name (not including the null-terminator).
- *
- * @return true if success, false otherwise.
- *
- */
-bool format_amount(char *dst,
- size_t dst_len,
- const uint64_t value,
- uint8_t decimals,
- const char *ticker,
- size_t ticker_len);
-
-/**
- * Format 16-bit unsigned integer as string with decimals and percentage sign.
- *
- * @param[out] dst
- * Pointer to output string.
- * @param[in] dst_len
- * Length of output string.
- * @param[in] value
- * 16-bit unsigned integer to format.
- * @param[in] decimals
- * Number of digits after decimal separator.
- *
- * @return true if success, false otherwise.
- *
- */
-bool format_percentage(char *dst, size_t dst_len, const uint16_t value, uint8_t decimals);
-
-/**
- * Format byte buffer to uppercase hexadecimal string.
- *
- * @param[in] in
- * Pointer to input byte buffer.
- * @param[in] in_len
- * Length of input byte buffer.
- * @param[out] out
- * Pointer to output string.
- * @param[in] out_len
- * Length of output string.
- *
- * @return number of bytes written if success, -1 otherwise.
- *
- */
-int format_hex(const uint8_t *in, size_t in_len, char *out, size_t out_len);
diff --git a/src/common/macros.h b/src/common/macros.h
deleted file mode 100644
index 13f75a3c..00000000
--- a/src/common/macros.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#pragma once
-
-/**
- * Macro for the size of a specific structure field.
- */
-#define MEMBER_SIZE(type, member) (sizeof(((type *) 0)->member))
diff --git a/src/common/read.c b/src/common/read.c
deleted file mode 100644
index c8ee851f..00000000
--- a/src/common/read.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*****************************************************************************
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
-#include // uint*_t
-#include // size_t
-
-uint16_t read_u16_be(const uint8_t *ptr, size_t offset) {
- return (uint16_t) ptr[offset + 0] << 8 | //
- (uint16_t) ptr[offset + 1] << 0;
-}
-
-uint32_t read_u32_be(const uint8_t *ptr, size_t offset) {
- return (uint32_t) ptr[offset + 0] << 24 | //
- (uint32_t) ptr[offset + 1] << 16 | //
- (uint32_t) ptr[offset + 2] << 8 | //
- (uint32_t) ptr[offset + 3] << 0;
-}
-
-uint64_t read_u64_be(const uint8_t *ptr, size_t offset) {
- return (uint64_t) ptr[offset + 0] << 56 | //
- (uint64_t) ptr[offset + 1] << 48 | //
- (uint64_t) ptr[offset + 2] << 40 | //
- (uint64_t) ptr[offset + 3] << 32 | //
- (uint64_t) ptr[offset + 4] << 24 | //
- (uint64_t) ptr[offset + 5] << 16 | //
- (uint64_t) ptr[offset + 6] << 8 | //
- (uint64_t) ptr[offset + 7] << 0;
-}
-
-uint16_t read_u16_le(const uint8_t *ptr, size_t offset) {
- return (uint16_t) ptr[offset + 0] << 0 | //
- (uint16_t) ptr[offset + 1] << 8;
-}
-
-uint32_t read_u32_le(const uint8_t *ptr, size_t offset) {
- return (uint32_t) ptr[offset + 0] << 0 | //
- (uint32_t) ptr[offset + 1] << 8 | //
- (uint32_t) ptr[offset + 2] << 16 | //
- (uint32_t) ptr[offset + 3] << 24;
-}
-
-uint64_t read_u64_le(const uint8_t *ptr, size_t offset) {
- return (uint64_t) ptr[offset + 0] << 0 | //
- (uint64_t) ptr[offset + 1] << 8 | //
- (uint64_t) ptr[offset + 2] << 16 | //
- (uint64_t) ptr[offset + 3] << 24 | //
- (uint64_t) ptr[offset + 4] << 32 | //
- (uint64_t) ptr[offset + 5] << 40 | //
- (uint64_t) ptr[offset + 6] << 48 | //
- (uint64_t) ptr[offset + 7] << 56;
-}
diff --git a/src/common/read.h b/src/common/read.h
deleted file mode 100644
index 61cfa8c0..00000000
--- a/src/common/read.h
+++ /dev/null
@@ -1,82 +0,0 @@
-#pragma once
-
-#include // uint*_t
-#include // size_t
-
-/**
- * Read 2 bytes as Big Endian from byte buffer.
- *
- * @param[in] ptr
- * Pointer to byte buffer.
- * @param[in] offset
- * Offset in the byte buffer.
- *
- * @return 2 bytes value read from buffer.
- *
- */
-uint16_t read_u16_be(const uint8_t *ptr, size_t offset);
-
-/**
- * Read 4 bytes as Big Endian from byte buffer.
- *
- * @param[in] ptr
- * Pointer to byte buffer.
- * @param[in] offset
- * Offset in the byte buffer.
- *
- * @return 4 bytes value read from buffer.
- *
- */
-uint32_t read_u32_be(const uint8_t *ptr, size_t offset);
-
-/**
- * Read 8 bytes as Big Endian from byte buffer.
- *
- * @param[in] ptr
- * Pointer to byte buffer.
- * @param[in] offset
- * Offset in the byte buffer.
- *
- * @return 8 bytes value read from buffer.
- *
- */
-uint64_t read_u64_be(const uint8_t *ptr, size_t offset);
-
-/**
- * Read 2 bytes as Little Endian from byte buffer.
- *
- * @param[in] ptr
- * Pointer to byte buffer.
- * @param[in] offset
- * Offset in the byte buffer.
- *
- * @return 2 bytes value read from buffer.
- *
- */
-uint16_t read_u16_le(const uint8_t *ptr, size_t offset);
-
-/**
- * Read 4 bytes as Little Endian from byte buffer.
- *
- * @param[in] ptr
- * Pointer to byte buffer.
- * @param[in] offset
- * Offset in the byte buffer.
- *
- * @return 4 bytes value read from buffer.
- *
- */
-uint32_t read_u32_le(const uint8_t *ptr, size_t offset);
-
-/**
- * Read 8 bytes as Little Endian from byte buffer.
- *
- * @param[in] ptr
- * Pointer to byte buffer.
- * @param[in] offset
- * Offset in the byte buffer.
- *
- * @return 8 bytes value read from buffer.
- *
- */
-uint64_t read_u64_le(const uint8_t *ptr, size_t offset);
diff --git a/src/common/varint.c b/src/common/varint.c
deleted file mode 100644
index d04fbb27..00000000
--- a/src/common/varint.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*****************************************************************************
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
-#include // uint*_t
-#include // size_t
-#include // bool
-
-#include "varint.h"
-#include "write.h"
-#include "read.h"
-
-uint8_t varint_size(uint64_t value) {
- if (value <= 0xFC) {
- return 1;
- }
-
- if (value <= UINT16_MAX) {
- return 3;
- }
-
- if (value <= UINT32_MAX) {
- return 5;
- }
-
- return 9; // <= UINT64_MAX
-}
-
-int varint_read(const uint8_t *in, size_t in_len, uint64_t *value) {
- if (in_len < 1) {
- return -1;
- }
-
- uint8_t prefix = in[0];
-
- if (prefix == 0xFD) {
- if (in_len < 3) {
- return -1;
- }
- *value = (uint64_t) read_u16_le(in, 1);
- return 3;
- }
-
- if (prefix == 0xFE) {
- if (in_len < 5) {
- return -1;
- }
- *value = (uint64_t) read_u32_le(in, 1);
- return 5;
- }
-
- if (prefix == 0xFF) {
- if (in_len < 9) {
- return -1;
- }
- *value = (uint64_t) read_u64_le(in, 1);
- return 9;
- }
-
- *value = (uint64_t) prefix; // prefix <= 0xFC
-
- return 1;
-}
-
-int varint_write(uint8_t *out, size_t offset, uint64_t value) {
- uint8_t varint_len = varint_size(value);
-
- switch (varint_len) {
- case 1:
- out[offset] = (uint8_t) value;
- break;
- case 3:
- out[offset++] = 0xFD;
- write_u16_le(out, offset, (uint16_t) value);
- break;
- case 5:
- out[offset++] = 0xFE;
- write_u32_le(out, offset, (uint32_t) value);
- break;
- case 9:
- out[offset++] = 0xFF;
- write_u64_le(out, offset, (uint64_t) value);
- break;
- default:
- return -1;
- }
-
- return varint_len;
-}
diff --git a/src/common/varint.h b/src/common/varint.h
deleted file mode 100644
index 80aeb430..00000000
--- a/src/common/varint.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#pragma once
-
-#include // uint*_t
-#include // size_t
-#include // bool
-
-/**
- * Size of value represented as Bitcoin-like varint.
- *
- * @see https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer
- *
- * @param[in] value
- * 64-bit unsigned integer to compute varint size.
- *
- * @return number of bytes to write value as varint (1, 3, 5 or 9 bytes).
- *
- */
-uint8_t varint_size(uint64_t value);
-
-/**
- * Read Bitcoin-like varint from byte buffer.
- *
- * @see https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer
- *
- * @param[in] in
- * Pointer to input byte buffer.
- * @param[in] in_len
- * Length of the input byte buffer.
- * @param[out] value
- * Pointer to 64-bit unsigned integer to output varint.
- *
- * @return number of bytes read (1, 3, 5 or 9 bytes), -1 otherwise.
- *
- */
-int varint_read(const uint8_t *in, size_t in_len, uint64_t *value);
-
-/**
- * Write Bitcoin-like varint to byte buffer.
- *
- * @see https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer
- *
- * @param[out] out
- * Pointer to output byte buffer.
- * @param[in] offset
- * Offset in the output byte buffer.
- * @param[in] value
- * 64-bit unsigned integer to write as varint.
- *
- * @return number of bytes written (1, 3, 5 or 9 bytes), -1 otherwise.
- *
- */
-int varint_write(uint8_t *out, size_t offset, uint64_t value);
diff --git a/src/common/write.c b/src/common/write.c
deleted file mode 100644
index 43cc5519..00000000
--- a/src/common/write.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
-#include // uint*_t
-#include // size_t
-
-void write_u16_be(uint8_t *ptr, size_t offset, uint16_t value) {
- ptr[offset + 0] = (uint8_t)(value >> 8);
- ptr[offset + 1] = (uint8_t)(value >> 0);
-}
-
-void write_u32_be(uint8_t *ptr, size_t offset, uint32_t value) {
- ptr[offset + 0] = (uint8_t)(value >> 24);
- ptr[offset + 1] = (uint8_t)(value >> 16);
- ptr[offset + 2] = (uint8_t)(value >> 8);
- ptr[offset + 3] = (uint8_t)(value >> 0);
-}
-
-void write_u64_be(uint8_t *ptr, size_t offset, uint64_t value) {
- ptr[offset + 0] = (uint8_t)(value >> 56);
- ptr[offset + 1] = (uint8_t)(value >> 48);
- ptr[offset + 2] = (uint8_t)(value >> 40);
- ptr[offset + 3] = (uint8_t)(value >> 32);
- ptr[offset + 4] = (uint8_t)(value >> 24);
- ptr[offset + 5] = (uint8_t)(value >> 16);
- ptr[offset + 6] = (uint8_t)(value >> 8);
- ptr[offset + 7] = (uint8_t)(value >> 0);
-}
-
-void write_u16_le(uint8_t *ptr, size_t offset, uint16_t value) {
- ptr[offset + 0] = (uint8_t)(value >> 0);
- ptr[offset + 1] = (uint8_t)(value >> 8);
-}
-
-void write_u32_le(uint8_t *ptr, size_t offset, uint32_t value) {
- ptr[offset + 0] = (uint8_t)(value >> 0);
- ptr[offset + 1] = (uint8_t)(value >> 8);
- ptr[offset + 2] = (uint8_t)(value >> 16);
- ptr[offset + 3] = (uint8_t)(value >> 24);
-}
-
-void write_u64_le(uint8_t *ptr, size_t offset, uint64_t value) {
- ptr[offset + 0] = (uint8_t)(value >> 0);
- ptr[offset + 1] = (uint8_t)(value >> 8);
- ptr[offset + 2] = (uint8_t)(value >> 16);
- ptr[offset + 3] = (uint8_t)(value >> 24);
- ptr[offset + 4] = (uint8_t)(value >> 32);
- ptr[offset + 5] = (uint8_t)(value >> 40);
- ptr[offset + 6] = (uint8_t)(value >> 48);
- ptr[offset + 7] = (uint8_t)(value >> 56);
-}
diff --git a/src/common/write.h b/src/common/write.h
deleted file mode 100644
index 0418f5c6..00000000
--- a/src/common/write.h
+++ /dev/null
@@ -1,82 +0,0 @@
-#pragma once
-
-#include // uint*_t
-#include // size_t
-
-/**
- * Write 16-bit unsigned integer value as Big Endian.
- *
- * @param[out] ptr
- * Pointer to output byte buffer.
- * @param[in] offset
- * Offset in the output byte buffer.
- * @param[in] value
- * 16-bit unsigned integer to write in output byte buffer as Big Endian.
- *
- */
-void write_u16_be(const uint8_t *ptr, size_t offset, uint16_t value);
-
-/**
- * Write 32-bit unsigned integer value as Big Endian.
- *
- * @param[out] ptr
- * Pointer to output byte buffer.
- * @param[in] offset
- * Offset in the output byte buffer.
- * @param[in] value
- * 32-bit unsigned integer to write in output byte buffer as Big Endian.
- *
- */
-void write_u32_be(uint8_t *ptr, size_t offset, uint32_t value);
-
-/**
- * Write 64-bit unsigned integer value as Big Endian.
- *
- * @param[out] ptr
- * Pointer to output byte buffer.
- * @param[in] offset
- * Offset in the output byte buffer.
- * @param[in] value
- * 64-bit unsigned integer to write in output byte buffer as Big Endian.
- *
- */
-void write_u64_be(uint8_t *ptr, size_t offset, uint64_t value);
-
-/**
- * Write 16-bit unsigned integer value as Little Endian.
- *
- * @param[out] ptr
- * Pointer to output byte buffer.
- * @param[in] offset
- * Offset in the output byte buffer.
- * @param[in] value
- * 16-bit unsigned integer to write in output byte buffer as Little Endian.
- *
- */
-void write_u16_le(uint8_t *ptr, size_t offset, uint16_t value);
-
-/**
- * Write 32-bit unsigned integer value as Little Endian.
- *
- * @param[out] ptr
- * Pointer to output byte buffer.
- * @param[in] offset
- * Offset in the output byte buffer.
- * @param[in] value
- * 32-bit unsigned integer to write in output byte buffer as Little Endian.
- *
- */
-void write_u32_le(uint8_t *ptr, size_t offset, uint32_t value);
-
-/**
- * Write 64-bit unsigned integer value as Little Endian.
- *
- * @param[out] ptr
- * Pointer to output byte buffer.
- * @param[in] offset
- * Offset in the output byte buffer.
- * @param[in] value
- * 64-bit unsigned integer to write in output byte buffer as Little Endian.
- *
- */
-void write_u64_le(uint8_t *ptr, size_t offset, uint64_t value);
diff --git a/src/constants.h b/src/constants.h
index 716ad324..db22ce7c 100644
--- a/src/constants.h
+++ b/src/constants.h
@@ -1,32 +1,14 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
#pragma once
/**
- * Instruction class of the Solar application.
+ * String length of a Solar address.
*/
-#define CLA 0xE0
+#define ADDRESS_LEN 34
+
+/**
+ * Length of the address hash ([network/version(1), pubKeyHash(20)]).
+ */
+#define ADDRESS_HASH_LEN 21
/**
* Length of APPNAME variable in the Makefile.
@@ -34,19 +16,19 @@
#define APPNAME_LEN (sizeof(APPNAME) - 1)
/**
- * Maximum length of MAJOR_VERSION || MINOR_VERSION || PATCH_VERSION.
+ * Maximum length of application name.
*/
-#define APPVERSION_LEN 3
+#define APPNAME_MAX_LEN 64
/**
- * Maximum length of application name.
+ * Maximum length of MAJOR_VERSION || MINOR_VERSION || PATCH_VERSION.
*/
-#define MAX_APPNAME_LEN 64
+#define APPVERSION_LEN 3
/**
- * Maximum transaction length (bytes).
+ * Instruction class of the Solar application.
*/
-#define MAX_TRANSACTION_LEN 1600
+#define CLA 0xE0
/**
* Exponent used to convert SXP unit (N SXP = N * 10^8).
@@ -63,16 +45,6 @@
*/
#define HASH_64_LEN 64
-/**
- * Length of the address hash ([network/version(1), pubKeyHash(20)]).
- */
-#define ADDRESS_HASH_LEN 21
-
-/**
- * String length of a Solar address.
- */
-#define ADDRESS_LEN 34
-
/**
* Solar Mainnet Network Byte
*/
@@ -94,16 +66,11 @@
#define SIG_SCHNORR_LEN 64
/**
- * Max length for memo.
- */
-#define MAX_MEMO_LEN 255
-
-/**
- * Max length for the hash on HTLC transactions.
+ * The default ticker name used for displaying amounts.
*/
-#define MAX_HTLC_HASH_LEN 192
+#define TICKER_DEFAULT "SXP"
/**
- * The default ticker name used for displaying amounts.
+ * Maximum transaction length (bytes).
*/
-#define TICKER_DEFAULT "SXP"
+#define TRANSACTION_MAX_LEN 1600
diff --git a/src/context.c b/src/context.c
index 5c66a47f..b9797a73 100644
--- a/src/context.c
+++ b/src/context.c
@@ -5,9 +5,12 @@
* 4.0 International License.
*****************************************************************************/
+#include "context.h"
+
#include // explicit_bzero
-#include "context.h"
+#include "os.h" // PRINTF
+
#include "globals.h"
void reset_app_context() {
diff --git a/src/context.h b/src/context.h
index 5cab5887..61256aa1 100644
--- a/src/context.h
+++ b/src/context.h
@@ -1,10 +1,3 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
#pragma once
/**
diff --git a/src/crypto/crypto.c b/src/crypto/crypto.c
index 24218ee3..eaca5df0 100644
--- a/src/crypto/crypto.c
+++ b/src/crypto/crypto.c
@@ -1,4 +1,11 @@
/*****************************************************************************
+ * Copyright (c) Solar Network
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ *****************************************************************************
+ *
* This work is licensed under a Creative Commons Attribution-NoDerivatives
* 4.0 International License.
*
@@ -6,7 +13,7 @@
* and permission notice:
*
* Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
+ * (c) Ledger SAS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +31,8 @@
#include // uint*_t
#include // memset, explicit_bzero
+#include "crypto_helpers.h"
+
#include "crypto.h"
#include "globals.h"
@@ -32,30 +41,13 @@ int crypto_derive_private_key(cx_ecfp_private_key_t *private_key,
uint8_t chain_code[32],
const uint32_t *bip32_path,
uint8_t bip32_path_len) {
- uint8_t raw_private_key[32] = {0};
-
- BEGIN_TRY {
- TRY {
- // derive the seed with bip32_path
- os_perso_derive_node_bip32(CX_CURVE_256K1,
- bip32_path,
- bip32_path_len,
- raw_private_key,
- chain_code);
- // new private_key from raw
- cx_ecfp_init_private_key(CX_CURVE_256K1,
- raw_private_key,
- sizeof(raw_private_key),
- private_key);
- }
- CATCH_OTHER(e) {
- THROW(e);
- }
- FINALLY {
- explicit_bzero(&raw_private_key, sizeof(raw_private_key));
- }
+ if (bip32_derive_init_privkey_256(CX_CURVE_256K1,
+ bip32_path,
+ bip32_path_len,
+ private_key,
+ chain_code) != CX_OK) {
+ return -1;
}
- END_TRY;
return 0;
}
@@ -64,7 +56,9 @@ int crypto_init_public_key(cx_ecfp_private_key_t *private_key,
cx_ecfp_public_key_t *public_key,
uint8_t raw_public_key[33]) {
// generate corresponding public key
- cx_ecfp_generate_pair(CX_CURVE_256K1, public_key, private_key, 1);
+ if (cx_ecfp_generate_pair_no_throw(CX_CURVE_256K1, public_key, private_key, true) != CX_OK) {
+ return -1;
+ }
raw_public_key[0] = ((*(public_key->W + 64) & 1) ? 0x03 : 0x02);
memmove(raw_public_key + 1, public_key->W + 1, 32);
@@ -75,29 +69,19 @@ int crypto_init_public_key(cx_ecfp_private_key_t *private_key,
int crypto_sign_message() {
cx_ecfp_private_key_t private_key = {0};
size_t signature_len = sizeof(G_context.tx_info.signature);
- cx_err_t error = CX_INTERNAL_ERROR;
// derive private key according to BIP32 path
crypto_derive_private_key(&private_key, NULL, G_context.bip32_path, G_context.bip32_path_len);
- BEGIN_TRY {
- TRY {
- error = cx_ecschnorr_sign_no_throw(&private_key,
- CX_ECSCHNORR_BIP0340 | CX_RND_TRNG,
- CX_SHA256,
- G_context.tx_info.m_hash,
- sizeof(G_context.tx_info.m_hash),
- G_context.tx_info.signature,
- &signature_len);
- }
- CATCH_OTHER(e) {
- THROW(e);
- }
- FINALLY {
- explicit_bzero(&private_key, sizeof(private_key));
- }
- }
- END_TRY;
+ cx_err_t error = cx_ecschnorr_sign_no_throw(&private_key,
+ CX_ECSCHNORR_BIP0340 | CX_RND_TRNG,
+ CX_SHA256,
+ G_context.tx_info.m_hash,
+ sizeof(G_context.tx_info.m_hash),
+ G_context.tx_info.signature,
+ &signature_len);
+
+ explicit_bzero(&private_key, sizeof(private_key));
if (error != CX_OK) {
return -1;
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index affa1632..0dd9eda9 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -1,32 +1,9 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
#pragma once
#include // uint*_t
-#include "os.h"
#include "cx.h"
+#include "os.h"
/**
* Derive private key given BIP32 path.
diff --git a/src/globals.h b/src/globals.h
index 175ebf7c..049e8120 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -2,11 +2,11 @@
#include
+#include "io.h"
#include "ux.h"
-#include "io.h"
-#include "types.h"
#include "constants.h"
+#include "types.h"
/**
* Global buffer for interactions between SE and MCU.
@@ -14,7 +14,7 @@
extern uint8_t G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B];
/**
- * Global variable with the lenght of APDU response to send back.
+ * Global variable with the length of APDU response to send back.
*/
extern uint32_t G_output_len;
diff --git a/src/handler/get_address.c b/src/handler/get_address.c
index b622fd8a..0a43394e 100644
--- a/src/handler/get_address.c
+++ b/src/handler/get_address.c
@@ -3,30 +3,52 @@
*
* This work is licensed under a Creative Commons Attribution-NoDerivatives
* 4.0 International License.
+ *
+ *****************************************************************************
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ * This software also incorporates work covered by the following copyright
+ * and permission notice:
+ *
+ * Ledger App Boilerplate.
+ * (c) Ledger SAS.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*****************************************************************************/
-#include "get_public_key.h"
+#include "get_address.h"
#include // uint*_t
#include // bool
#include // size_t
#include // memset, explicit_bzero
-#include "os.h"
#include "cx.h"
+#include "io.h"
+#include "os.h"
-#include "../io.h"
-#include "../sw.h"
-#include "../context.h"
-
-#include "../globals.h"
-#include "../types.h"
+#include "buffer.h"
-#include "../common/buffer.h"
-#include "../crypto/crypto.h"
+#include "context.h"
+#include "globals.h"
+#include "sw.h"
+#include "types.h"
-#include "../ui/display.h"
-#include "../helper/send_response.h"
+#include "crypto/crypto.h"
+#include "helper/send_response.h"
+#include "ui/display.h"
int handler_get_address(buffer_t *cdata, bool user_approval, uint8_t network) {
reset_app_context();
diff --git a/src/handler/get_address.h b/src/handler/get_address.h
index ca8ac2ef..b89f9b45 100644
--- a/src/handler/get_address.h
+++ b/src/handler/get_address.h
@@ -1,17 +1,9 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
#pragma once
-#include // size_t
#include // bool
#include // uint*_t
-#include "../common/buffer.h"
+#include "buffer.h"
/**
* Handler for GET_ADDRESS command.
diff --git a/src/handler/get_app_name.c b/src/handler/get_app_name.c
index ea440ae8..8ba27938 100644
--- a/src/handler/get_app_name.c
+++ b/src/handler/get_app_name.c
@@ -1,4 +1,11 @@
/*****************************************************************************
+ * Copyright (c) Solar Network
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ *****************************************************************************
+ *
* This work is licensed under a Creative Commons Attribution-NoDerivatives
* 4.0 International License.
*
@@ -6,7 +13,7 @@
* and permission notice:
*
* Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
+ * (c) Ledger SAS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,19 +28,18 @@
* limitations under the License.
*****************************************************************************/
-#include // uint*_t
-
#include "get_app_name.h"
-#include "../constants.h"
-#include "../io.h"
-#include "../sw.h"
-#include "../types.h"
-#include "common/buffer.h"
-int handler_get_app_name() {
- _Static_assert(APPNAME_LEN < MAX_APPNAME_LEN, "APPNAME must be at most 64 characters!");
+#include "buffer.h"
+#include "io.h"
+#include "os.h"
- buffer_t rdata = {.ptr = (uint8_t *) PIC(APPNAME), .size = APPNAME_LEN, .offset = 0};
+#include "constants.h"
+#include "sw.h"
+#include "types.h"
+
+int handler_get_app_name() {
+ _Static_assert(APPNAME_LEN < APPNAME_MAX_LEN, "APPNAME must be at most 64 characters!");
- return io_send_response(&rdata, SW_OK);
+ return io_send_response_pointer(PIC(APPNAME), APPNAME_LEN, SW_OK);
}
diff --git a/src/handler/get_app_name.h b/src/handler/get_app_name.h
index b568b1f3..45653e8f 100644
--- a/src/handler/get_app_name.h
+++ b/src/handler/get_app_name.h
@@ -1,7 +1,5 @@
#pragma once
-#include "os.h"
-
/**
* Handler for GET_APP_NAME command. Send APDU response with ASCII
* encoded name of the application.
diff --git a/src/handler/get_public_key.c b/src/handler/get_public_key.c
index 71cef894..4b2bd7c3 100644
--- a/src/handler/get_public_key.c
+++ b/src/handler/get_public_key.c
@@ -1,4 +1,11 @@
/*****************************************************************************
+ * Copyright (c) Solar Network
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ *****************************************************************************
+ *
* This work is licensed under a Creative Commons Attribution-NoDerivatives
* 4.0 International License.
*
@@ -6,7 +13,7 @@
* and permission notice:
*
* Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
+ * (c) Ledger SAS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,18 +35,19 @@
#include // size_t
#include // memset, explicit_bzero
-#include "os.h"
+#include "buffer.h"
#include "cx.h"
+#include "io.h"
+#include "os.h"
+
+#include "context.h"
+#include "globals.h"
+#include "types.h"
+#include "sw.h"
-#include "../globals.h"
-#include "../types.h"
-#include "../context.h"
-#include "../io.h"
-#include "../sw.h"
-#include "../crypto/crypto.h"
-#include "../common/buffer.h"
-#include "../ui/display.h"
-#include "../helper/send_response.h"
+#include "crypto/crypto.h"
+#include "helper/send_response.h"
+#include "ui/display.h"
int handler_get_public_key(buffer_t *cdata, bool user_approval, bool use_chain_code) {
reset_app_context();
diff --git a/src/handler/get_public_key.h b/src/handler/get_public_key.h
index b743f8e0..3de5222b 100644
--- a/src/handler/get_public_key.h
+++ b/src/handler/get_public_key.h
@@ -1,33 +1,8 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
#pragma once
-#include // size_t
#include // bool
-#include // uint*_t
-#include "../common/buffer.h"
+#include "buffer.h"
/**
* Handler for GET_PUBLIC_KEY command. If it successfully parses BIP32 path,
diff --git a/src/handler/get_version.c b/src/handler/get_version.c
index d9c96a4c..b3052296 100644
--- a/src/handler/get_version.c
+++ b/src/handler/get_version.c
@@ -1,4 +1,11 @@
/*****************************************************************************
+ * Copyright (c) Solar Network
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ *****************************************************************************
+ *
* This work is licensed under a Creative Commons Attribution-NoDerivatives
* 4.0 International License.
*
@@ -6,7 +13,7 @@
* and permission notice:
*
* Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
+ * (c) Ledger SAS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,16 +28,18 @@
* limitations under the License.
*****************************************************************************/
+#include "get_version.h"
+
#include // uint*_t
#include // UINT8_MAX
#include // _Static_assert
-#include "get_version.h"
-#include "../constants.h"
-#include "../io.h"
-#include "../sw.h"
-#include "../types.h"
-#include "common/buffer.h"
+#include "io.h"
+#include "buffer.h"
+
+#include "constants.h"
+#include "sw.h"
+#include "types.h"
int handler_get_version() {
_Static_assert(APPVERSION_LEN == 3, "Length of (MAJOR || MINOR || PATCH) must be 3!");
@@ -41,11 +50,10 @@ int handler_get_version() {
_Static_assert(PATCH_VERSION >= 0 && PATCH_VERSION <= UINT8_MAX,
"PATCH version must be between 0 and 255!");
- return io_send_response(
- &(const buffer_t){.ptr = (uint8_t[APPVERSION_LEN]){(uint8_t) MAJOR_VERSION,
- (uint8_t) MINOR_VERSION,
- (uint8_t) PATCH_VERSION},
- .size = APPVERSION_LEN,
- .offset = 0},
+ return io_send_response_pointer(
+ (const uint8_t *) &(uint8_t[APPVERSION_LEN]){(uint8_t) MAJOR_VERSION,
+ (uint8_t) MINOR_VERSION,
+ (uint8_t) PATCH_VERSION},
+ APPVERSION_LEN,
SW_OK);
}
diff --git a/src/handler/sign_tx.c b/src/handler/sign_tx.c
index e37cdd25..01c9dabf 100644
--- a/src/handler/sign_tx.c
+++ b/src/handler/sign_tx.c
@@ -1,4 +1,11 @@
/*****************************************************************************
+ * Copyright (c) Solar Network
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ *****************************************************************************
+ *
* This work is licensed under a Creative Commons Attribution-NoDerivatives
* 4.0 International License.
*
@@ -6,7 +13,7 @@
* and permission notice:
*
* Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
+ * (c) Ledger SAS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,23 +28,26 @@
* limitations under the License.
*****************************************************************************/
+#include "sign_tx.h"
+
#include // uint*_t
#include // bool
#include // size_t
#include // memset, explicit_bzero
-#include "os.h"
#include "cx.h"
+#include "os.h"
+#include "sw.h"
-#include "sign_tx.h"
-#include "../sw.h"
-#include "../globals.h"
-#include "../context.h"
-#include "../crypto/crypto.h"
-#include "../ui/display.h"
-#include "../common/buffer.h"
-#include "../transaction/types.h"
-#include "../transaction/deserialise.h"
+#include "buffer.h"
+
+#include "context.h"
+#include "crypto.h"
+#include "globals.h"
+
+#include "transaction/deserialise.h"
+#include "transaction/types.h"
+#include "ui/display.h"
int handler_sign_tx(buffer_t *cdata, uint8_t chunk, bool more, bool is_message) {
if (chunk == 0) { // first APDU, parse BIP32 path
@@ -71,7 +81,7 @@ int handler_sign_tx(buffer_t *cdata, uint8_t chunk, bool more, bool is_message)
G_context.req_num++;
if (more) { // more APDUs with transaction part
- if (G_context.tx_info.raw_tx_len + cdata->size > MAX_TRANSACTION_LEN || //
+ if (G_context.tx_info.raw_tx_len + cdata->size > TRANSACTION_MAX_LEN || //
cdata->size < UINT8_MAX || //
!buffer_move(cdata,
G_context.tx_info.raw_tx + G_context.tx_info.raw_tx_len,
@@ -83,7 +93,7 @@ int handler_sign_tx(buffer_t *cdata, uint8_t chunk, bool more, bool is_message)
return io_send_sw(SW_OK);
} else { // last APDU, let's parse and sign
- if (G_context.tx_info.raw_tx_len + cdata->size > MAX_TRANSACTION_LEN || //
+ if (G_context.tx_info.raw_tx_len + cdata->size > TRANSACTION_MAX_LEN || //
!buffer_move(cdata,
G_context.tx_info.raw_tx + G_context.tx_info.raw_tx_len,
cdata->size)) {
@@ -110,17 +120,19 @@ int handler_sign_tx(buffer_t *cdata, uint8_t chunk, bool more, bool is_message)
G_context.state = STATE_PARSED;
cx_sha256_t sha256;
- cx_sha256_init(&sha256);
- cx_hash(&sha256.header,
- CX_LAST,
- (G_context.req_type == CONFIRM_MESSAGE) ? G_context.tx_info.raw_tx + 2
- : G_context.tx_info.raw_tx,
- (G_context.req_type == CONFIRM_MESSAGE) ? G_context.tx_info.raw_tx_len - 2
- : G_context.tx_info.raw_tx_len,
- G_context.tx_info.m_hash,
- sizeof(G_context.tx_info.m_hash));
-
- PRINTF("Hash: %.*H\n", sizeof(G_context.tx_info.m_hash), G_context.tx_info.m_hash);
+
+ if (cx_sha256_init_no_throw(&sha256) != CX_OK) {
+ return io_send_sw(SW_TX_HASH_FAIL);
+ }
+
+ if (cx_hash_no_throw((cx_hash_t *) &sha256,
+ CX_LAST,
+ G_context.tx_info.raw_tx,
+ G_context.tx_info.raw_tx_len,
+ G_context.tx_info.m_hash,
+ HASH_32_LEN) != CX_OK) {
+ return io_send_sw(SW_TX_HASH_FAIL);
+ }
if (G_context.req_type == CONFIRM_TRANSACTION) {
return ui_display_transaction();
diff --git a/src/handler/sign_tx.h b/src/handler/sign_tx.h
index 472f319a..493360b0 100644
--- a/src/handler/sign_tx.h
+++ b/src/handler/sign_tx.h
@@ -1,32 +1,9 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
#pragma once
#include // uint*_t
#include // bool
-#include "../common/buffer.h"
+#include "buffer.h"
/**
* Handler for SIGN_TX command. If successfully parse BIP32 path
diff --git a/src/helper/send_reponse.c b/src/helper/send_response.c
similarity index 81%
rename from src/helper/send_reponse.c
rename to src/helper/send_response.c
index bc4b68d7..9c9e6533 100644
--- a/src/helper/send_reponse.c
+++ b/src/helper/send_response.c
@@ -1,4 +1,11 @@
/*****************************************************************************
+ * Copyright (c) Solar Network
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ *****************************************************************************
+ *
* This work is licensed under a Creative Commons Attribution-NoDerivatives
* 4.0 International License.
*
@@ -6,7 +13,7 @@
* and permission notice:
*
* Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
+ * (c) Ledger SAS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,17 +28,19 @@
* limitations under the License.
*****************************************************************************/
+#include "send_response.h"
+
#include // size_t
#include // uint*_t
#include // memmove
-#include "send_response.h"
-#include "../constants.h"
-#include "../globals.h"
-#include "../context.h"
-#include "../sw.h"
-#include "common/buffer.h"
-#include "../address.h"
+#include "buffer.h"
+
+#include "address.h"
+#include "constants.h"
+#include "context.h"
+#include "globals.h"
+#include "sw.h"
int helper_send_response_pubkey() {
uint8_t resp[1 + PUBLIC_KEY_LEN + 1 + CHAINCODE_LEN] = {0};
@@ -49,7 +58,7 @@ int helper_send_response_pubkey() {
reset_app_context();
- return io_send_response(&(const buffer_t){.ptr = resp, .size = offset, .offset = 0}, SW_OK);
+ return io_send_response_pointer(resp, offset, SW_OK);
}
int helper_send_response_address() {
@@ -76,7 +85,7 @@ int helper_send_response_address() {
reset_app_context();
- return io_send_response(&(const buffer_t){.ptr = resp, .size = offset, .offset = 0}, SW_OK);
+ return io_send_response_pointer(resp, offset, SW_OK);
}
int helper_send_response_sig() {
@@ -84,6 +93,5 @@ int helper_send_response_sig() {
memmove(resp, G_context.tx_info.signature, SIG_SCHNORR_LEN);
- return io_send_response(&(const buffer_t){.ptr = resp, .size = SIG_SCHNORR_LEN, .offset = 0},
- SW_OK);
+ return io_send_response_pointer(resp, SIG_SCHNORR_LEN, SW_OK);
}
diff --git a/src/helper/send_response.h b/src/helper/send_response.h
index 6ba72603..5340d948 100644
--- a/src/helper/send_response.h
+++ b/src/helper/send_response.h
@@ -1,31 +1,8 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
#pragma once
#include "os.h"
-#include "../common/macros.h"
+#include "macros.h"
/**
* Length of chain code.
diff --git a/src/io.c b/src/io.c
deleted file mode 100644
index fa66dbc0..00000000
--- a/src/io.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
-#include
-
-#include "os.h"
-#include "ux.h"
-
-#include "io.h"
-#include "globals.h"
-#include "context.h"
-#include "sw.h"
-#include "common/buffer.h"
-#include "common/write.h"
-
-uint32_t G_output_len = 0;
-
-void io_seproxyhal_display(const bagl_element_t *element) {
- io_seproxyhal_display_default((bagl_element_t *) element);
-}
-
-uint8_t io_event(uint8_t channel __attribute__((unused))) {
- switch (G_io_seproxyhal_spi_buffer[0]) {
- case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT:
- UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer);
- break;
- case SEPROXYHAL_TAG_STATUS_EVENT:
- if (G_io_apdu_media == IO_APDU_MEDIA_USB_HID && //
- !(U4BE(G_io_seproxyhal_spi_buffer, 3) & //
- SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED)) {
- THROW(EXCEPTION_IO_RESET);
- }
- /* fallthrough */
- case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT:
- UX_DISPLAYED_EVENT({});
- break;
- case SEPROXYHAL_TAG_TICKER_EVENT:
- UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {});
- break;
- default:
- UX_DEFAULT_EVENT();
- break;
- }
-
- if (!io_seproxyhal_spi_is_status_sent()) {
- io_seproxyhal_general_status();
- }
-
- return 1;
-}
-
-uint16_t io_exchange_al(uint8_t channel, uint16_t tx_len) {
- switch (channel & ~(IO_FLAGS)) {
- case CHANNEL_KEYBOARD:
- break;
- case CHANNEL_SPI:
- if (tx_len) {
- io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len);
-
- if (channel & IO_RESET_AFTER_REPLIED) {
- halt();
- }
-
- return 0;
- } else {
- return io_seproxyhal_spi_recv(G_io_apdu_buffer, sizeof(G_io_apdu_buffer), 0);
- }
- default:
- THROW(INVALID_PARAMETER);
- }
-
- return 0;
-}
-
-int io_recv_command() {
- int ret;
-
- switch (G_io_state) {
- case READY:
- G_io_state = RECEIVED;
- ret = io_exchange(CHANNEL_APDU, G_output_len);
- break;
- case RECEIVED:
- G_io_state = WAITING;
- ret = io_exchange(CHANNEL_APDU | IO_ASYNCH_REPLY, G_output_len);
- G_io_state = RECEIVED;
- break;
- case WAITING:
- G_io_state = READY;
- ret = -1;
- break;
- }
-
- return ret;
-}
-
-int io_send_response(const buffer_t *rdata, uint16_t sw) {
- int ret;
-
- if (rdata != NULL) {
- if (rdata->size - rdata->offset > IO_APDU_BUFFER_SIZE - 2 || //
- !buffer_copy(rdata, G_io_apdu_buffer, sizeof(G_io_apdu_buffer))) {
- return io_send_sw(SW_WRONG_RESPONSE_LENGTH);
- }
- G_output_len = rdata->size - rdata->offset;
- PRINTF("<= SW=%04X | RData=%.*H\n", sw, rdata->size, rdata->ptr);
- } else {
- G_output_len = 0;
- PRINTF("<= SW=%04X | RData=\n", sw);
- }
-
- write_u16_be(G_io_apdu_buffer, G_output_len, sw);
- G_output_len += 2;
-
- switch (G_io_state) {
- case READY:
- ret = -1;
- break;
- case RECEIVED:
- G_io_state = READY;
- ret = 0;
- break;
- case WAITING:
- ret = io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, G_output_len);
- G_output_len = 0;
- G_io_state = READY;
- break;
- }
-
- if (sw != 0x9000) {
- reset_app_context();
- }
-
- return ret;
-}
-
-int io_send_sw(uint16_t sw) {
- return io_send_response(NULL, sw);
-}
diff --git a/src/io.h b/src/io.h
deleted file mode 100644
index d6a31a83..00000000
--- a/src/io.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#pragma once
-
-#include
-
-#include "ux.h"
-#include "os_io_seproxyhal.h"
-
-#include "types.h"
-#include "common/buffer.h"
-
-void io_seproxyhal_display(const bagl_element_t *element);
-
-/**
- * IO callback called when an interrupt based channel has received
- * data to be processed.
- *
- * @return 1 if success, 0 otherwise.
- *
- */
-uint8_t io_event(uint8_t channel __attribute__((unused)));
-
-uint16_t io_exchange_al(uint8_t channel, uint16_t tx_len);
-
-/**
- * Receive APDU command in G_io_apdu_buffer and update G_output_len.
- *
- * @return zero or positive integer if success, -1 otherwise.
- *
- */
-int io_recv_command(void);
-
-/**
- * Send APDU response (response data + status word) by filling
- * G_io_apdu_buffer.
- *
- * @param[in] rdata
- * Buffer with APDU response data.
- * @param[in] sw
- * Status word of APDU response.
- *
- * @return zero or positive integer if success, -1 otherwise.
- *
- */
-int io_send_response(const buffer_t *rdata, uint16_t sw);
-
-/**
- * Send APDU response (only status word) by filling
- * G_io_apdu_buffer.
- *
- * @param[in] sw
- * Status word of APDU response.
- *
- * @return zero or positive integer if success, -1 otherwise.
- *
- */
-int io_send_sw(uint16_t sw);
diff --git a/src/main.c b/src/main.c
deleted file mode 100644
index c3cd365b..00000000
--- a/src/main.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
-#include // uint*_t
-#include // memset, explicit_bzero
-
-#include "os.h"
-#include "ux.h"
-
-#include "types.h"
-#include "globals.h"
-#include "io.h"
-#include "sw.h"
-#include "context.h"
-#include "ui/menu.h"
-#include "apdu/parser.h"
-#include "apdu/dispatcher.h"
-
-uint8_t G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B];
-io_state_e G_io_state;
-ux_state_t G_ux;
-bolos_ux_params_t G_ux_params;
-global_ctx_t G_context;
-
-/**
- * Handle APDU command received and send back APDU response using handlers.
- */
-void app_main() {
- // Length of APDU command received in G_io_apdu_buffer
- int input_len = 0;
- // Structured APDU command
- command_t cmd;
-
- // Reset length of APDU response
- G_output_len = 0;
- G_io_state = READY;
-
- // Reset context
- reset_app_context();
-
- for (;;) {
- BEGIN_TRY {
- TRY {
- // Reset structured APDU command
- memset(&cmd, 0, sizeof(cmd));
-
- // Receive command bytes in G_io_apdu_buffer
- if ((input_len = io_recv_command()) < 0) {
- CLOSE_TRY;
- return;
- }
-
- // Parse APDU command from G_io_apdu_buffer
- if (!apdu_parser(&cmd, G_io_apdu_buffer, input_len)) {
- PRINTF("=> /!\\ BAD LENGTH: %.*H\n", input_len, G_io_apdu_buffer);
- io_send_sw(SW_WRONG_DATA_LENGTH);
- CLOSE_TRY;
- continue;
- }
-
- PRINTF("=> CLA=%02X | INS=%02X | P1=%02X | P2=%02X | Lc=%02X | CData=%.*H\n",
- cmd.cla,
- cmd.ins,
- cmd.p1,
- cmd.p2,
- cmd.lc,
- cmd.lc,
- cmd.data);
-
- // Dispatch structured APDU command to handler
- if (apdu_dispatcher(&cmd) < 0) {
- CLOSE_TRY;
- return;
- }
- }
- CATCH(EXCEPTION_IO_RESET) {
- THROW(EXCEPTION_IO_RESET);
- }
- CATCH_OTHER(e) {
- io_send_sw(e);
- }
- FINALLY {
- }
- END_TRY;
- }
- }
-}
-
-/**
- * Exit the application and go back to the dashboard.
- */
-void app_exit() {
- BEGIN_TRY_L(exit) {
- TRY_L(exit) {
- os_sched_exit(-1);
- }
- FINALLY_L(exit) {
- }
- }
- END_TRY_L(exit);
-}
-
-/**
- * Main loop to setup USB, Bluetooth, UI and launch app_main().
- */
-__attribute__((section(".boot"))) int main() {
- __asm volatile("cpsie i");
-
- os_boot();
-
- for (;;) {
- // Reset UI
- memset(&G_ux, 0, sizeof(G_ux));
-
- BEGIN_TRY {
- TRY {
- io_seproxyhal_init();
-
-#ifdef TARGET_NANOX
- G_io_app.plane_mode = os_setting_get(OS_SETTING_PLANEMODE, NULL, 0);
-#endif // TARGET_NANOX
-
- USB_power(0);
- USB_power(1);
-
- ui_menu_main();
-
-#ifdef HAVE_BLE
- BLE_power(0, NULL);
- BLE_power(1, "Nano X");
-#endif // HAVE_BLE
- app_main();
- }
- CATCH(EXCEPTION_IO_RESET) {
- CLOSE_TRY;
- continue;
- }
- CATCH_ALL {
- CLOSE_TRY;
- break;
- }
- FINALLY {
- }
- }
- END_TRY;
- }
-
- app_exit();
-
- return 0;
-}
diff --git a/src/sw.h b/src/sw.h
index 09ca355c..a2fc8678 100644
--- a/src/sw.h
+++ b/src/sw.h
@@ -1,26 +1,3 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
#pragma once
/**
@@ -36,7 +13,7 @@
*/
#define SW_WRONG_P1P2 0x6A86
/**
- * Status word for either wrong Lc or lenght of APDU command less than 5.
+ * Status word for either wrong Lc or length of APDU command less than 5.
*/
#define SW_WRONG_DATA_LENGTH 0x6A87
/**
@@ -48,7 +25,7 @@
*/
#define SW_CLA_NOT_SUPPORTED 0x6E00
/**
- * Status word for wrong reponse length (buffer too small or too big).
+ * Status word for wrong response length (buffer too small or too big).
*/
#define SW_WRONG_RESPONSE_LENGTH 0xB000
/**
diff --git a/src/transaction/deserialise.c b/src/transaction/deserialise.c
index 67c8ac75..1320a91a 100644
--- a/src/transaction/deserialise.c
+++ b/src/transaction/deserialise.c
@@ -1,4 +1,11 @@
/*****************************************************************************
+ * Copyright (c) Solar Network
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ *****************************************************************************
+ *
* This work is licensed under a Creative Commons Attribution-NoDerivatives
* 4.0 International License.
*
@@ -6,7 +13,7 @@
* and permission notice:
*
* Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
+ * (c) 2023 Ledger SAS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,10 +29,16 @@
*****************************************************************************/
#include "deserialise.h"
-#include "utils.h"
-#include "types.h"
-#include "../constants.h"
-#include "../common/buffer.h"
+
+#include // uint*_t
+
+#include "buffer.h"
+
+#include "constants.h"
+
+#include "transaction/errors.h"
+#include "transaction/transaction_utils.h"
+#include "transaction/types.h"
parser_status_e transaction_deserialise(buffer_t *buf, transaction_t *tx) {
parser_status_e parse_common = transaction_deserialise_common(buf, tx);
@@ -79,7 +92,7 @@ parser_status_e transaction_deserialise_common(buffer_t *buf, transaction_t *tx)
}
// nonce
- if (!buffer_seek_cur(buf, NONCE_LENGTH)) {
+ if (!buffer_seek_cur(buf, sizeof(uint64_t))) {
return WRONG_LENGTH_ERROR;
}
@@ -129,18 +142,10 @@ parser_status_e transaction_deserialise_core_asset(buffer_t *buf,
}
} else if (typeGroup == TYPEGROUP_CORE) {
switch (type) {
- case MULTISIGNATURE_REGISTRATION:
- return multisignature_type_deserialise(buf, &tx->Multisignature);
case IPFS:
return ipfs_type_deserialise(buf, &tx->Ipfs);
case TRANSFER:
return transfer_type_deserialise(buf, &tx->Transfer);
- case HTLC_LOCK:
- return htlc_lock_type_deserialise(buf, &tx->Htlc_lock);
- case HTLC_CLAIM:
- return htlc_claim_type_deserialise(buf, &tx->Htlc_claim);
- case HTLC_REFUND:
- return htlc_refund_type_deserialise(buf, &tx->Htlc_refund);
default:
return TYPE_PARSING_ERROR;
}
@@ -152,7 +157,7 @@ parser_status_e transaction_deserialise_core_asset(buffer_t *buf,
parser_status_e message_deserialise(buffer_t *buf, transaction_t *tx) {
// message length
if (!buffer_read_u16(buf, &tx->message_length, LE) || tx->message_length < 1 ||
- tx->message_length > MAX_TRANSACTION_LEN - 3) {
+ tx->message_length > TRANSACTION_MAX_LEN - 3) {
return WRONG_LENGTH_ERROR;
}
diff --git a/src/transaction/deserialise.h b/src/transaction/deserialise.h
index b8ce5df9..6b87bdf4 100644
--- a/src/transaction/deserialise.h
+++ b/src/transaction/deserialise.h
@@ -1,30 +1,10 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
#pragma once
-#include "types.h"
-#include "../common/buffer.h"
+#include // uint*_t
+
+#include "buffer.h"
+
+#include "transaction/types.h"
/**
* Deserialise raw transaction in structure.
diff --git a/src/transaction/errors.h b/src/transaction/errors.h
index c660c3df..484a5563 100644
--- a/src/transaction/errors.h
+++ b/src/transaction/errors.h
@@ -1,10 +1,3 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
#pragma once
typedef enum {
diff --git a/src/transaction/transaction_utils.c b/src/transaction/transaction_utils.c
new file mode 100644
index 00000000..03446ab2
--- /dev/null
+++ b/src/transaction/transaction_utils.c
@@ -0,0 +1,118 @@
+/*****************************************************************************
+ * Copyright (c) Solar Network
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ *****************************************************************************
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ * This software also incorporates work covered by the following copyright
+ * and permission notice:
+ *
+ * Ledger App Boilerplate.
+ * (c) 2023 Ledger SAS.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *****************************************************************************/
+
+#include "transaction/transaction_utils.h"
+
+#include // size_t
+#include // uint*_t
+#include // bool
+#include // strlen
+#include // snprintf
+
+#include "format.h"
+
+#include "ui/ui_utils.h"
+
+static bool _format_fpu64(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals) {
+ char buffer[21] = {0};
+
+ if (!format_u64(buffer, sizeof(buffer), value)) {
+ return false;
+ }
+
+ size_t digits = strlen(buffer);
+
+ if (digits <= decimals) {
+ if (dst_len <= 2 + decimals + 1) {
+ return false;
+ }
+ *dst++ = '0';
+ *dst++ = '.';
+ for (uint16_t i = 0; i < decimals - digits; i++, dst++) {
+ *dst = '0';
+ }
+ dst_len -= 2 + decimals - digits;
+ strncpy(dst, buffer, dst_len);
+ } else {
+ if (dst_len <= digits + 1) {
+ return false;
+ }
+
+ const size_t shift = digits - decimals;
+ memmove(dst, buffer, shift);
+ dst[shift] = '.';
+ strncpy(dst + shift + 1, buffer + shift, decimals);
+ }
+
+ return true;
+}
+
+bool format_amount(char *dst,
+ size_t dst_len,
+ const uint64_t value,
+ uint8_t decimals,
+ const char *ticker,
+ size_t ticker_len) {
+ char amount[22] = {0};
+ if (dst_len < sizeof(amount) + 5 || ticker_len > 5) {
+ return false;
+ }
+ if (!_format_fpu64(amount, sizeof(amount), value, decimals)) {
+ return false;
+ }
+
+ unpad_amount(amount, strlen(amount), 2);
+
+ snprintf(dst, dst_len, "%s%c%s", amount, get_ticker_line_break(amount), ticker);
+ return true;
+}
+
+bool format_percentage(char *dst, size_t dst_len, const uint16_t value, uint8_t decimals) {
+ char amount[22] = {0};
+ if (dst_len < 9) {
+ return false;
+ }
+ if (!_format_fpu64(amount, sizeof(amount), (const uint64_t) value, decimals)) {
+ return false;
+ }
+ snprintf(dst, dst_len, "%s%%", amount);
+ return true;
+}
+
+bool transaction_utils_check_ascii(const uint8_t *text, uint64_t text_len, bool allow_new_lines) {
+ for (uint64_t i = 0; i < text_len; i++) {
+ bool lf = text[i] == 0x0A;
+ bool crlf = text[i] == 0x0D && i + 1 < text_len && text[i + 1] == 0x0A;
+ if (!((allow_new_lines && (lf || crlf)) || (text[i] >= 0x20 && text[i] <= 0x7E))) {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/src/transaction/transaction_utils.h b/src/transaction/transaction_utils.h
new file mode 100644
index 00000000..b8828fbb
--- /dev/null
+++ b/src/transaction/transaction_utils.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include // size_t
+#include // uint*_t
+#include // bool
+
+/**
+ * Format 64-bit unsigned integer as string with decimals and ticker.
+ *
+ * @param[out] dst
+ * Pointer to output string.
+ * @param[in] dst_len
+ * Length of output string.
+ * @param[in] value
+ * 64-bit unsigned integer to format.
+ * @param[in] decimals
+ * Number of digits after decimal separator.
+ * @param[in] ticker
+ * The token's ticker name to be displayed.
+ * @param[in] ticker_len
+ * The length of the ticker name (not including the null-terminator).
+ *
+ * @return true if success, false otherwise.
+ *
+ */
+bool format_amount(char *dst,
+ size_t dst_len,
+ const uint64_t value,
+ uint8_t decimals,
+ const char *ticker,
+ size_t ticker_len);
+
+/**
+ * Format 16-bit unsigned integer as string with decimals and percentage sign.
+ *
+ * @param[out] dst
+ * Pointer to output string.
+ * @param[in] dst_len
+ * Length of output string.
+ * @param[in] value
+ * 16-bit unsigned integer to format.
+ * @param[in] decimals
+ * Number of digits after decimal separator.
+ *
+ * @return true if success, false otherwise.
+ *
+ */
+bool format_percentage(char *dst, size_t dst_len, const uint16_t value, uint8_t decimals);
+
+/**
+ * Check if input is encoded using ASCII characters.
+ *
+ * @param[in] text
+ * Pointer to input byte buffer.
+ * @param[in] text_len
+ * Length of input byte buffer.
+ * @param[in] allow_new_lines
+ * Allow ASCII text to contain new lines.
+ *
+ * @return true if success, false otherwise.
+ *
+ */
+bool transaction_utils_check_ascii(const uint8_t *text, uint64_t text_len, bool allow_new_lines);
diff --git a/src/transaction/types.h b/src/transaction/types.h
index 6720c7d4..85a8ec7b 100644
--- a/src/transaction/types.h
+++ b/src/transaction/types.h
@@ -1,48 +1,15 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
#pragma once
-//#include // size_t
#include // uint*_t
-#include "types/types.h"
+
+#include "transaction/types/types.h"
#define STARTING_BYTE 0xFF
#define TRANSACTION_VERSION_3 0x03
-#define NONCE_LENGTH 0x08
-#define MAX_MEMO_LEN 255
typedef enum { TYPEGROUP_CORE = 1, TYPEGROUP_SOLAR = 2 } transaction_typegroup;
-typedef enum {
- MULTISIGNATURE_REGISTRATION = 4,
- IPFS = 5,
- TRANSFER = 6,
- HTLC_LOCK = 8,
- HTLC_CLAIM = 9,
- HTLC_REFUND = 10
-} transaction_type_core;
-
+typedef enum { IPFS = 5, TRANSFER = 6 } transaction_type_core;
typedef enum { BURN = 0, VOTE = 2 } transaction_type_solar;
typedef struct {
@@ -52,10 +19,10 @@ typedef struct {
// Transaction
uint32_t typeGroup; /// typeGroup (4 bytes)
uint16_t type; /// type (2 bytes)
- uint8_t *sender_publickey; /// sender publick key (33 bytes)
+ uint8_t *sender_publickey; /// sender public key (33 bytes)
uint64_t fee; /// fee (8 bytes)
uint8_t memo_len; /// length of memo (1 byte)
- uint8_t *memo; /// memo (MAX lenth 255)
+ uint8_t *memo; /// memo (MAX length 255)
transaction_asset_t core_asset; /// transaction specific assets (variable length and structure)
} transaction_t;
diff --git a/src/transaction/types/burn.c b/src/transaction/types/burn.c
index 1ee89f56..ca3effa5 100644
--- a/src/transaction/types/burn.c
+++ b/src/transaction/types/burn.c
@@ -6,8 +6,12 @@
*****************************************************************************/
#include "burn.h"
+
+#include "buffer.h"
+
#include "constants.h"
-#include "../../common/buffer.h"
+
+#include "transaction/errors.h"
parser_status_e burn_type_deserialise(buffer_t *buf, burn_transaction_asset_t *tx) {
// amount
diff --git a/src/transaction/types/burn.h b/src/transaction/types/burn.h
index 6cb44974..8705020b 100644
--- a/src/transaction/types/burn.h
+++ b/src/transaction/types/burn.h
@@ -1,14 +1,8 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
#pragma once
-#include "../errors.h"
-#include "../../common/buffer.h"
+#include "buffer.h"
+
+#include "transaction/errors.h"
typedef struct {
uint64_t amount; /// amount (8 bytes)
diff --git a/src/transaction/types/htlc_claim.c b/src/transaction/types/htlc_claim.c
deleted file mode 100644
index 955ebfff..00000000
--- a/src/transaction/types/htlc_claim.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#include "htlc_claim.h"
-#include "constants.h"
-#include "../../common/buffer.h"
-
-parser_status_e htlc_claim_type_deserialise(buffer_t *buf, htlc_claim_transaction_asset_t *tx) {
- // hash type
- if (!buffer_read_u8(buf, &tx->hash_type)) {
- return WRONG_LENGTH_ERROR;
- }
-
- // lock transaction id
- tx->lockId = (uint8_t *) (buf->ptr + buf->offset);
-
- if (!buffer_seek_cur(buf, HASH_32_LEN)) {
- return WRONG_LENGTH_ERROR;
- }
-
- // unlock secret length
- if (!buffer_read_u8(buf, &tx->unlock_secret_length)) {
- return WRONG_LENGTH_ERROR;
- }
-
- if (tx->unlock_secret_length < 1 || tx->unlock_secret_length > MAX_HTLC_HASH_LEN) {
- return CORE_ASSET_PARSING_ERROR;
- }
-
- // unlock secret
- tx->unlock_secret = (uint8_t *) (buf->ptr + buf->offset);
-
- if (!buffer_seek_cur(buf, tx->unlock_secret_length)) {
- return WRONG_LENGTH_ERROR;
- }
-
- return (buf->offset == buf->size) ? PARSING_OK : WRONG_LENGTH_ERROR;
-}
diff --git a/src/transaction/types/htlc_claim.h b/src/transaction/types/htlc_claim.h
deleted file mode 100644
index f60ea87c..00000000
--- a/src/transaction/types/htlc_claim.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#pragma once
-
-#include "../errors.h"
-#include "../../common/buffer.h"
-
-typedef struct {
- uint8_t hash_type; /// hashing algorithm (1 byte)
- uint8_t *lockId; /// lock transaction id (32 bytes)
- uint8_t unlock_secret_length; /// lock secret length (1 byte)
- uint8_t *unlock_secret; /// unlock secret (1-255 bytes)
-} htlc_claim_transaction_asset_t;
-
-/**
- * Deserialise asset of transaction in structure.
- *
- * @param[in, out] buf
- * Pointer to buffer with serialised transaction.
- * @param[out] tx
- * Pointer to transaction asset structure.
- *
- * @return PARSING_OK if success, error status otherwise.
- *
- */
-parser_status_e htlc_claim_type_deserialise(buffer_t *buf, htlc_claim_transaction_asset_t *tx);
diff --git a/src/transaction/types/htlc_lock.c b/src/transaction/types/htlc_lock.c
deleted file mode 100644
index 6bf82941..00000000
--- a/src/transaction/types/htlc_lock.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#include "htlc_lock.h"
-#include "constants.h"
-#include "../../common/buffer.h"
-
-parser_status_e htlc_lock_type_deserialise(buffer_t *buf, htlc_lock_transaction_asset_t *tx) {
- // amount
- if (!buffer_read_u64(buf, &tx->amount, LE)) {
- return WRONG_LENGTH_ERROR;
- }
-
- // secret hash length
- if (!buffer_read_u8(buf, &tx->secret_hash_length)) {
- return WRONG_LENGTH_ERROR;
- }
-
- if (tx->secret_hash_length < 1 || tx->secret_hash_length > MAX_HTLC_HASH_LEN) {
- return CORE_ASSET_PARSING_ERROR;
- }
-
- // secret hash
- tx->secret_hash = (uint8_t *) (buf->ptr + buf->offset);
-
- if (!buffer_seek_cur(buf, tx->secret_hash_length)) {
- return WRONG_LENGTH_ERROR;
- }
-
- // expiration type
- if (!buffer_read_u8(buf, &tx->expiration_type)) {
- return WRONG_LENGTH_ERROR;
- }
-
- // expiration value
- if (!buffer_read_u32(buf, &tx->expiration_value, LE)) {
- return WRONG_LENGTH_ERROR;
- }
-
- // recipientId
- tx->recipientId = (uint8_t *) (buf->ptr + buf->offset);
-
- if (!buffer_seek_cur(buf, ADDRESS_HASH_LEN)) {
- return WRONG_LENGTH_ERROR;
- }
-
- return (buf->offset == buf->size) ? PARSING_OK : WRONG_LENGTH_ERROR;
-}
diff --git a/src/transaction/types/htlc_lock.h b/src/transaction/types/htlc_lock.h
deleted file mode 100644
index 2f2f8747..00000000
--- a/src/transaction/types/htlc_lock.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#pragma once
-
-#include "../errors.h"
-#include "../../common/buffer.h"
-
-typedef struct {
- uint64_t amount; /// Amount (8 bytes)
- uint8_t secret_hash_length; /// Secret hash length (1 byte)
- uint8_t *secret_hash; /// secret hash (1-255 bytes)
- uint8_t expiration_type; /// expiration type (1 byte)
- uint32_t expiration_value; /// expiration value (4 bytes)
- uint8_t *recipientId; /// recipientId (MAX 21 bytes)
-} htlc_lock_transaction_asset_t;
-
-/**
- * Deserialise asset of transaction in structure.
- *
- * @param[in, out] buf
- * Pointer to buffer with serialised transaction.
- * @param[out] tx
- * Pointer to transaction asset structure.
- *
- * @return PARSING_OK if success, error status otherwise.
- *
- */
-parser_status_e htlc_lock_type_deserialise(buffer_t *buf, htlc_lock_transaction_asset_t *tx);
diff --git a/src/transaction/types/htlc_refund.c b/src/transaction/types/htlc_refund.c
deleted file mode 100644
index d9eebc63..00000000
--- a/src/transaction/types/htlc_refund.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#include "htlc_refund.h"
-#include "constants.h"
-#include "../../common/buffer.h"
-
-parser_status_e htlc_refund_type_deserialise(buffer_t *buf, htlc_refund_transaction_asset_t *tx) {
- // lock transaction id
- tx->lockId = (uint8_t *) (buf->ptr + buf->offset);
-
- if (!buffer_seek_cur(buf, HASH_32_LEN)) {
- return WRONG_LENGTH_ERROR;
- }
-
- return (buf->offset == buf->size) ? PARSING_OK : WRONG_LENGTH_ERROR;
-}
diff --git a/src/transaction/types/htlc_refund.h b/src/transaction/types/htlc_refund.h
deleted file mode 100644
index 29346802..00000000
--- a/src/transaction/types/htlc_refund.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#pragma once
-
-#include "../errors.h"
-#include "../../common/buffer.h"
-
-typedef struct {
- uint8_t *lockId; /// lock transaction id (32 bytes)
-} htlc_refund_transaction_asset_t;
-
-/**
- * Deserialise asset of transaction in structure.
- *
- * @param[in, out] buf
- * Pointer to buffer with serialised transaction.
- * @param[out] tx
- * Pointer to transaction asset structure.
- *
- * @return PARSING_OK if success, error status otherwise.
- *
- */
-parser_status_e htlc_refund_type_deserialise(buffer_t *buf, htlc_refund_transaction_asset_t *tx);
diff --git a/src/transaction/types/ipfs.c b/src/transaction/types/ipfs.c
index af4266ca..711fb73f 100644
--- a/src/transaction/types/ipfs.c
+++ b/src/transaction/types/ipfs.c
@@ -6,8 +6,12 @@
*****************************************************************************/
#include "ipfs.h"
+
+#include "buffer.h"
+
#include "constants.h"
-#include "../../common/buffer.h"
+
+#include "transaction/errors.h"
parser_status_e ipfs_type_deserialise(buffer_t *buf, ipfs_transaction_asset_t *tx) {
// ipfs
diff --git a/src/transaction/types/ipfs.h b/src/transaction/types/ipfs.h
index 5f8ce097..2ea08f7a 100644
--- a/src/transaction/types/ipfs.h
+++ b/src/transaction/types/ipfs.h
@@ -1,14 +1,8 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
#pragma once
-#include "../errors.h"
-#include "../../common/buffer.h"
+#include "buffer.h"
+
+#include "transaction/errors.h"
typedef struct {
uint8_t ipfs_length; /// ipfs length (1 byte)
diff --git a/src/transaction/types/multi_signature_registration.c b/src/transaction/types/multi_signature_registration.c
deleted file mode 100644
index 897c8c60..00000000
--- a/src/transaction/types/multi_signature_registration.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#include "multi_signature_registration.h"
-#include "constants.h"
-#include "../../common/buffer.h"
-
-parser_status_e multisignature_type_deserialise(buffer_t *buf,
- multisignature_transaction_asset_t *tx) {
- // min
- if (!buffer_read_u8(buf, &tx->min)) {
- return WRONG_LENGTH_ERROR;
- }
-
- // count
- if (!buffer_read_u8(buf, &tx->pkey_length)) {
- return WRONG_LENGTH_ERROR;
- }
-
- if (tx->pkey_length < MIN_NUM_SIGNATURES || tx->pkey_length > MAX_NUM_SIGNATURES) {
- return CORE_ASSET_PARSING_ERROR;
- }
-
- // public keys
- tx->pkeys = (uint8_t *) (buf->ptr + buf->offset);
-
- if (!buffer_seek_cur(buf, PUBLIC_KEY_LEN * tx->pkey_length)) {
- return WRONG_LENGTH_ERROR;
- }
-
- return (buf->offset == buf->size) ? PARSING_OK : WRONG_LENGTH_ERROR;
-}
diff --git a/src/transaction/types/multi_signature_registration.h b/src/transaction/types/multi_signature_registration.h
deleted file mode 100644
index fd47bfa3..00000000
--- a/src/transaction/types/multi_signature_registration.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#pragma once
-
-#include "../errors.h"
-#include "../../common/buffer.h"
-
-#define MIN_NUM_SIGNATURES 2
-#define MAX_NUM_SIGNATURES 16
-
-typedef struct {
- uint8_t min; /// multisignatures minimum (1 byte)
- uint8_t pkey_length; /// number of public keys (1 byte)
- uint8_t *pkeys; /// publickeys (MAX 33 * 16 bytes)
-} multisignature_transaction_asset_t;
-
-/**
- * Deserialise asset of transaction in structure.
- *
- * @param[in, out] buf
- * Pointer to buffer with serialised transaction.
- * @param[out] tx
- * Pointer to transaction asset structure.
- *
- * @return PARSING_OK if success, error status otherwise.
- *
- */
-parser_status_e multisignature_type_deserialise(buffer_t *buf,
- multisignature_transaction_asset_t *tx);
diff --git a/src/transaction/types/transfer.c b/src/transaction/types/transfer.c
index 4b7c5270..fa6ca786 100644
--- a/src/transaction/types/transfer.c
+++ b/src/transaction/types/transfer.c
@@ -6,8 +6,12 @@
*****************************************************************************/
#include "transfer.h"
+
+#include "buffer.h"
+
#include "constants.h"
-#include "../../common/buffer.h"
+
+#include "transaction/errors.h"
parser_status_e transfer_type_deserialise(buffer_t *buf, transfer_transaction_asset_t *tx) {
// length
diff --git a/src/transaction/types/transfer.h b/src/transaction/types/transfer.h
index 57ee96be..6a2d90a4 100644
--- a/src/transaction/types/transfer.h
+++ b/src/transaction/types/transfer.h
@@ -1,14 +1,8 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
#pragma once
-#include "../errors.h"
-#include "../../common/buffer.h"
+#include "buffer.h"
+
+#include "transaction/errors.h"
#define MIN_NUM_TRANSFERS 1
#define MAX_NUM_TRANSFERS 40 // Limited respect to protocol maximum due to SRAM limitations
diff --git a/src/transaction/types/types.h b/src/transaction/types/types.h
index 06b9bd4b..28fa4c42 100644
--- a/src/transaction/types/types.h
+++ b/src/transaction/types/types.h
@@ -1,28 +1,13 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
#pragma once
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
+#include "transaction/types/ipfs.h"
+#include "transaction/types/transfer.h"
+#include "transaction/types/burn.h"
+#include "transaction/types/vote.h"
typedef union transaction_asset_t {
- multisignature_transaction_asset_t Multisignature;
ipfs_transaction_asset_t Ipfs;
transfer_transaction_asset_t Transfer;
- htlc_lock_transaction_asset_t Htlc_lock;
- htlc_claim_transaction_asset_t Htlc_claim;
- htlc_refund_transaction_asset_t Htlc_refund;
burn_transaction_asset_t Burn;
vote_transaction_asset_t Vote;
} transaction_asset_t;
diff --git a/src/transaction/types/vote.c b/src/transaction/types/vote.c
index 6d78fb65..7517158e 100644
--- a/src/transaction/types/vote.c
+++ b/src/transaction/types/vote.c
@@ -6,9 +6,15 @@
*****************************************************************************/
#include "vote.h"
+
+#include // uint*_t
+
+#include "buffer.h"
+
#include "constants.h"
-#include "../utils.h"
-#include "../../common/buffer.h"
+
+#include "transaction/errors.h"
+#include "transaction/transaction_utils.h"
parser_status_e vote_type_deserialise(buffer_t *buf, vote_transaction_asset_t *tx) {
// length
@@ -16,7 +22,7 @@ parser_status_e vote_type_deserialise(buffer_t *buf, vote_transaction_asset_t *t
return WRONG_LENGTH_ERROR;
}
- if (tx->vote_length < MIN_NUM_VOTES || tx->vote_length > MAX_NUM_VOTES) {
+ if (tx->vote_length > MAX_NUM_VOTES) {
return CORE_ASSET_PARSING_ERROR;
}
diff --git a/src/transaction/types/vote.h b/src/transaction/types/vote.h
index 96308db1..1feac84d 100644
--- a/src/transaction/types/vote.h
+++ b/src/transaction/types/vote.h
@@ -1,16 +1,11 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
#pragma once
-#include "../errors.h"
-#include "../../common/buffer.h"
+#include // uint*_t
+
+#include "buffer.h"
+
+#include "transaction/errors.h"
-#define MIN_NUM_VOTES 0
#define MAX_NUM_VOTES 53
#define MIN_USERNAME_LENGTH 1
#define MAX_USERNAME_LENGTH 20
diff --git a/src/transaction/utils.c b/src/transaction/utils.c
deleted file mode 100644
index f4950b8a..00000000
--- a/src/transaction/utils.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
-#include // uint*_t
-#include // bool
-#include // memmove
-
-#include "types.h"
-
-bool transaction_utils_check_ascii(const uint8_t *text, uint64_t text_len, bool allow_new_lines) {
- for (uint64_t i = 0; i < text_len; i++) {
- bool lf = text[i] == 0x0A;
- bool crlf = text[i] == 0x0D && i + 1 < text_len && text[i + 1] == 0x0A;
- if (!((allow_new_lines && (lf || crlf)) || (text[i] >= 0x20 && text[i] <= 0x7E))) {
- return false;
- }
- }
- return true;
-}
diff --git a/src/transaction/utils.h b/src/transaction/utils.h
deleted file mode 100644
index a928e838..00000000
--- a/src/transaction/utils.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
-#pragma once
-
-#include // uint*_t
-#include // bool
-
-#include "types.h"
-
-/**
- * Check if input is encoded using ASCII characters.
- *
- * @param[in] text
- * Pointer to input byte buffer.
- * @param[in] text_len
- * Lenght of input byte buffer.
- * @param[in] allow_new_lines
- * Allow ASCII text to contain new lines.
- *
- * @return true if success, false otherwise.
- *
- */
-bool transaction_utils_check_ascii(const uint8_t *text, uint64_t text_len, bool allow_new_lines);
diff --git a/src/types.h b/src/types.h
index c09f4695..128dc4f1 100644
--- a/src/types.h
+++ b/src/types.h
@@ -1,44 +1,14 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
#pragma once
#include // bool
#include // size_t
#include // uint*_t
+#include "bip32.h"
+
#include "constants.h"
-#include "transaction/types.h"
-#include "common/bip32.h"
-/**
- * Enumeration for the status of IO.
- */
-typedef enum {
- READY, /// ready for new event
- RECEIVED, /// data received
- WAITING /// waiting
-} io_state_e;
+#include "transaction/types.h"
/**
* Enumeration with expected INS of APDU commands.
@@ -52,18 +22,6 @@ typedef enum {
SIGN_TX = 0xc2 /// sign transaction with BIP32 path
} command_e;
-/**
- * Structure with fields of APDU command.
- */
-typedef struct {
- uint8_t cla; /// Instruction class
- command_e ins; /// Instruction code
- uint8_t p1; /// Instruction parameter 1
- uint8_t p2; /// Instruction parameter 2
- uint8_t lc; /// Lenght of command data
- uint8_t *data; /// Command data
-} command_t;
-
/**
* Enumeration with parsing state.
*/
@@ -96,7 +54,7 @@ typedef struct {
* Structure for transaction information context.
*/
typedef struct {
- uint8_t raw_tx[MAX_TRANSACTION_LEN]; /// raw transaction serialised
+ uint8_t raw_tx[TRANSACTION_MAX_LEN]; /// raw transaction serialised
size_t raw_tx_len; /// length of raw transaction
transaction_t transaction; /// structured transaction
uint8_t m_hash[32]; /// message hash digest
@@ -115,6 +73,6 @@ typedef struct {
};
request_type_e req_type; /// user request
uint32_t bip32_path[MAX_BIP32_PATH]; /// BIP32 path
- uint8_t bip32_path_len; /// lenght of BIP32 path
+ uint8_t bip32_path_len; /// length of BIP32 path
uint8_t network; /// network byte
} global_ctx_t;
diff --git a/src/ui/action/validate.c b/src/ui/action/validate.c
index 32bf8264..9b5443ac 100644
--- a/src/ui/action/validate.c
+++ b/src/ui/action/validate.c
@@ -1,4 +1,11 @@
/*****************************************************************************
+ * Copyright (c) Solar Network
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ *****************************************************************************
+ *
* This work is licensed under a Creative Commons Attribution-NoDerivatives
* 4.0 International License.
*
@@ -6,7 +13,7 @@
* and permission notice:
*
* Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
+ * (c) Ledger SAS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,16 +28,19 @@
* limitations under the License.
*****************************************************************************/
+#include "ui/action/validate.h"
+
#include // bool
-#include "validate.h"
-#include "../menu.h"
-#include "../../sw.h"
-#include "../../io.h"
-#include "../../crypto/crypto.h"
-#include "../../globals.h"
-#include "../../context.h"
-#include "../../helper/send_response.h"
+#include "io.h"
+
+#include "context.h"
+#include "globals.h"
+#include "sw.h"
+
+#include "crypto/crypto.h"
+#include "helper/send_response.h"
+#include "ui/menu.h"
void ui_action_validate_pubkey(bool choice) {
if (choice) {
diff --git a/src/ui/action/validate.h b/src/ui/action/validate.h
index 0b904cf2..5fd1bdff 100644
--- a/src/ui/action/validate.h
+++ b/src/ui/action/validate.h
@@ -1,26 +1,3 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
#pragma once
#include // bool
diff --git a/src/ui/ctx.c b/src/ui/ctx.c
index 201068e4..b79b20ae 100644
--- a/src/ui/ctx.c
+++ b/src/ui/ctx.c
@@ -5,8 +5,9 @@
* 4.0 International License.
*****************************************************************************/
-#include
-#include "../transaction/types.h"
+#include "ui/ctx.h"
+
+#include "transaction/types.h"
bool context_get_next(ctx_t *ctx, transaction_t *tx, char title[], char text[]) {
bool result = ctx->f(tx, title, text, ctx->offset);
diff --git a/src/ui/ctx.h b/src/ui/ctx.h
index 373c5504..7447e50c 100644
--- a/src/ui/ctx.h
+++ b/src/ui/ctx.h
@@ -1,16 +1,9 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
#pragma once
-#include
-#include
+#include // bool
+#include // uint*_t
-#include "../transaction/types.h"
+#include "transaction/types.h"
#define MAX_TITLE_LEN 16
#define MAX_TEXT_LEN 385
@@ -24,7 +17,7 @@ typedef struct {
* Get next content to display.
*
* @param[in, out] ctx
- * Pointer to the contect structure.
+ * Pointer to the context structure.
* @param[in] tx
* Pointer to transaction structure.
* @param[out] title
@@ -41,7 +34,7 @@ bool context_get_next(ctx_t *ctx, transaction_t *tx, char title[], char text[]);
* Get previous content to display.
*
* @param[in, out] ctx
- * Pointer to the contect structure.
+ * Pointer to the context structure.
* @param[in] tx
* Pointer to transaction structure.
* @param[out] title
diff --git a/src/ui/display.c b/src/ui/display.c
index 2baf8bf4..cc26b31c 100644
--- a/src/ui/display.c
+++ b/src/ui/display.c
@@ -1,4 +1,11 @@
/*****************************************************************************
+ * Copyright (c) Solar Network
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ *****************************************************************************
+ *
* This work is licensed under a Creative Commons Attribution-NoDerivatives
* 4.0 International License.
*
@@ -6,7 +13,7 @@
* and permission notice:
*
* Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
+ * (c) 2023 Ledger SAS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,34 +28,32 @@
* limitations under the License.
*****************************************************************************/
-#include "display.h"
+#include "ui/display.h"
#include // bool
#include // memset
+#include "glyphs.h"
+
+#include "bip32.h"
+#include "buffer.h"
+#include "format.h"
+#include "io.h"
#include "os.h"
#include "ux.h"
-#include "glyphs.h"
+#include "address.h"
#include "constants.h"
-#include "ctx.h"
-#include "../globals.h"
-#include "../io.h"
-#include "../sw.h"
+#include "globals.h"
+#include "sw.h"
+
#include "action/validate.h"
-#include "../transaction/types.h"
-#include "../common/bip32.h"
-#include "../common/buffer.h"
-#include "../common/format.h"
-#include "../address.h"
-#include "transactions/multi_signature_registration_display.h"
-#include "transactions/ipfs_display.h"
-#include "transactions/transfer_display.h"
-#include "transactions/htlc_lock_display.h"
-#include "transactions/htlc_claim_display.h"
-#include "transactions/htlc_refund_display.h"
-#include "transactions/burn_display.h"
-#include "transactions/vote_display.h"
+#include "transaction/types.h"
+#include "ui/ctx.h"
+#include "ui/transactions/ipfs_display.h"
+#include "ui/transactions/transfer_display.h"
+#include "ui/transactions/burn_display.h"
+#include "ui/transactions/vote_display.h"
ctx_t display_context = {0};
@@ -266,7 +271,7 @@ void display_next_state(bool is_upper_delimiter) {
}
}
-// Upper delimeter step
+// Upper delimiter step
UX_STEP_INIT(step_upper_delimiter, NULL, NULL, { display_next_state(true); });
// general dynamic step
@@ -277,7 +282,7 @@ UX_STEP_NOCB(ux_display_general,
.text = g_current_text,
});
-// Lower delimeter step
+// Lower delimiter step
UX_STEP_INIT(step_lower_delimiter, NULL, NULL, { display_next_state(false); });
// FLOW to display transaction:
@@ -326,12 +331,6 @@ int ui_display_transaction() {
}
} else {
switch (G_context.tx_info.transaction.type) {
- case MULTISIGNATURE_REGISTRATION: {
- snprintf(g_transaction_name, sizeof(g_transaction_name), "%s", "Multisignature");
-
- display_context.f = &multisignature_type_display;
- break;
- }
case IPFS: {
// First screen
snprintf(g_transaction_name, sizeof(g_transaction_name), "%s", "IPFS");
@@ -345,27 +344,6 @@ int ui_display_transaction() {
display_context.f = &transfer_type_display;
break;
}
- case HTLC_LOCK: {
- // First screen
- snprintf(g_transaction_name, sizeof(g_transaction_name), "%s", "HTLC Lock");
-
- display_context.f = &htlc_lock_type_display;
- break;
- }
- case HTLC_CLAIM: {
- // First screen
- snprintf(g_transaction_name, sizeof(g_transaction_name), "%s", "HTLC Claim");
-
- display_context.f = &htlc_claim_type_display;
- break;
- }
- case HTLC_REFUND: {
- // First screen
- snprintf(g_transaction_name, sizeof(g_transaction_name), "%s", "HTLC Refund");
-
- display_context.f = &htlc_refund_type_display;
- break;
- }
default:
return io_send_sw(SW_TX_PARSING_FAIL);
}
diff --git a/src/ui/display.h b/src/ui/display.h
index 50ae8ff8..51423004 100644
--- a/src/ui/display.h
+++ b/src/ui/display.h
@@ -1,26 +1,3 @@
-/*****************************************************************************
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *
- * This software also incorporates work covered by the following copyright
- * and permission notice:
- *
- * Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
#pragma once
#include // bool
diff --git a/src/ui/menu.c b/src/ui/menu.c
index 91eee668..c8d8cc9e 100644
--- a/src/ui/menu.c
+++ b/src/ui/menu.c
@@ -6,7 +6,7 @@
* and permission notice:
*
* Ledger App Boilerplate.
- * (c) 2020 Ledger SAS.
+ * (c) 2023 Ledger SAS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,12 +21,14 @@
* limitations under the License.
*****************************************************************************/
+#include "ui/menu.h"
+
+#include "glyphs.h"
+
#include "os.h"
#include "ux.h"
-#include "glyphs.h"
-#include "../globals.h"
-#include "menu.h"
+#include "globals.h"
UX_STEP_NOCB(ux_menu_ready_step, pnn, {&C_solar_logo, "Solar", "is ready"});
UX_STEP_NOCB(ux_menu_version_step, bn, {"Version", APPVERSION});
@@ -53,7 +55,7 @@ void ui_menu_main() {
ux_flow_init(0, ux_menu_main_flow, NULL);
}
-UX_STEP_NOCB(ux_menu_info_step, bn, {"Solar App", "(c) 2022 Solar"});
+UX_STEP_NOCB(ux_menu_info_step, bn, {"Solar App", "(c) Solar Network"});
UX_STEP_CB(ux_menu_back_step, pb, ui_menu_main(), {&C_icon_back, "Back"});
// FLOW for the about submenu:
diff --git a/src/ui/transactions/burn_display.c b/src/ui/transactions/burn_display.c
index 828f8e60..c998c29d 100644
--- a/src/ui/transactions/burn_display.c
+++ b/src/ui/transactions/burn_display.c
@@ -5,19 +5,25 @@
* 4.0 International License.
*****************************************************************************/
-#include
-#include "burn_display.h"
-#include "types.h"
+#include "ui/transactions/burn_display.h"
+
+#include // snprintf
+#include // uint*_t
+
+#include "base58.h"
+#include "buffer.h"
+
#include "constants.h"
-#include "../../common/buffer.h"
-#include "../../common/format.h"
-#include "../../common/base58.h"
+
+#include "transaction/transaction_utils.h"
+#include "transaction/types.h"
+#include "ui/ctx.h"
bool burn_type_display(transaction_t *tx, char title[], char text[], uint16_t step) {
switch (step) {
case 0: {
// Amount
- snprintf(title, MAX_TITLE_LEN, "%s", "Amount");
+ snprintf(title, MAX_TITLE_LEN, "Amount");
format_amount(text,
MAX_TEXT_LEN,
tx->core_asset.Burn.amount,
@@ -28,7 +34,7 @@ bool burn_type_display(transaction_t *tx, char title[], char text[], uint16_t st
}
case 1: {
// Fee
- snprintf(title, MAX_TITLE_LEN, "%s", "Fee");
+ snprintf(title, MAX_TITLE_LEN, "Fee");
format_amount(text,
MAX_TEXT_LEN,
tx->fee,
diff --git a/src/ui/transactions/burn_display.h b/src/ui/transactions/burn_display.h
index c139c40b..98570a40 100644
--- a/src/ui/transactions/burn_display.h
+++ b/src/ui/transactions/burn_display.h
@@ -1,15 +1,9 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
#pragma once
-#include
-#include "../../transaction/types.h"
-#include "../ctx.h"
+#include // bool
+#include // uint*_t
+
+#include "transaction/types.h"
/**
* Produce content for specific transaction.
diff --git a/src/ui/transactions/htlc_claim_display.c b/src/ui/transactions/htlc_claim_display.c
deleted file mode 100644
index 3b2f56b5..00000000
--- a/src/ui/transactions/htlc_claim_display.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#include
-#include "htlc_claim_display.h"
-#include "types.h"
-#include "constants.h"
-#include "../../common/buffer.h"
-#include "../../common/format.h"
-#include "../../common/base58.h"
-
-bool htlc_claim_type_display(transaction_t *tx, char title[], char text[], uint16_t step) {
- switch (step) {
- case 0: {
- // Lock Transaction Id
- snprintf(title, MAX_TITLE_LEN, "%s", "Lock ID");
- format_hex(tx->core_asset.Htlc_claim.lockId, HASH_32_LEN, text, MAX_TEXT_LEN);
- break;
- }
- case 1: {
- // Unlock secret
- snprintf(title, MAX_TITLE_LEN, "%s", "Unlock secret");
- format_hex(tx->core_asset.Htlc_claim.unlock_secret,
- tx->core_asset.Htlc_claim.unlock_secret_length,
- text,
- MAX_TEXT_LEN);
- break;
- }
- case 2: {
- // Fee
- snprintf(title, MAX_TITLE_LEN, "%s", "Fee");
- format_amount(text,
- MAX_TEXT_LEN,
- tx->fee,
- EXPONENT_SMALLEST_UNIT,
- TICKER_DEFAULT,
- sizeof(TICKER_DEFAULT));
- break;
- }
- default: {
- return false;
- }
- }
- return true;
-}
diff --git a/src/ui/transactions/htlc_claim_display.h b/src/ui/transactions/htlc_claim_display.h
deleted file mode 100644
index 5277b0b4..00000000
--- a/src/ui/transactions/htlc_claim_display.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#pragma once
-
-#include
-#include "../../transaction/types.h"
-#include "../ctx.h"
-
-/**
- * Produce content for specific transaction.
- *
- * @param[in] tx
- * Pointer to transaction structure.
- * @param[out] title
- * Title output.
- * @param[out] text
- * Text output.
- * @param[in] step
- * current step to display.
- *
- * @return true if there is content, false otherwise.
- *
- */
-bool htlc_claim_type_display(transaction_t *tx, char title[], char text[], uint16_t step);
diff --git a/src/ui/transactions/htlc_lock_display.c b/src/ui/transactions/htlc_lock_display.c
deleted file mode 100644
index b2ebedd9..00000000
--- a/src/ui/transactions/htlc_lock_display.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#include
-#include "htlc_lock_display.h"
-#include "types.h"
-#include "constants.h"
-#include "address.h"
-#include "../../common/buffer.h"
-#include "../../common/format.h"
-
-bool htlc_lock_type_display(transaction_t *tx, char title[], char text[], uint16_t step) {
- switch (step) {
- case 0: {
- // RecipientId
- snprintf(title, MAX_TITLE_LEN, "%s", "Recipient");
- base58_encode_address(tx->core_asset.Htlc_lock.recipientId,
- ADDRESS_HASH_LEN,
- text,
- MAX_TEXT_LEN);
- break;
- }
- case 1: {
- // Amount
- snprintf(title, MAX_TITLE_LEN, "%s", "Amount");
- format_amount(text,
- MAX_TEXT_LEN,
- tx->core_asset.Htlc_lock.amount,
- EXPONENT_SMALLEST_UNIT,
- TICKER_DEFAULT,
- sizeof(TICKER_DEFAULT));
- break;
- }
- case 2: {
- // Secret hash
- snprintf(title, MAX_TITLE_LEN, "%s", "Secret Hash");
- format_hex(tx->core_asset.Htlc_lock.secret_hash,
- tx->core_asset.Htlc_lock.secret_hash_length,
- text,
- MAX_TEXT_LEN);
- break;
- }
- case 3: {
- // Expiration
- bool isTime = tx->core_asset.Htlc_lock.expiration_type == 1;
- snprintf(title, MAX_TITLE_LEN, "%s", isTime ? "Expire Time" : "Expire Height");
- snprintf(text, MAX_TEXT_LEN, "%d", tx->core_asset.Htlc_lock.expiration_value);
- break;
- }
- case 4: {
- // Fee
- snprintf(title, MAX_TITLE_LEN, "%s", "Fee");
- format_amount(text,
- MAX_TEXT_LEN,
- tx->fee,
- EXPONENT_SMALLEST_UNIT,
- TICKER_DEFAULT,
- sizeof(TICKER_DEFAULT));
- break;
- }
- default: {
- return false;
- }
- }
-
- return true;
-}
diff --git a/src/ui/transactions/htlc_lock_display.h b/src/ui/transactions/htlc_lock_display.h
deleted file mode 100644
index f572b215..00000000
--- a/src/ui/transactions/htlc_lock_display.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#pragma once
-
-#include
-#include "../../transaction/types.h"
-#include "../ctx.h"
-
-/**
- * Produce content for specific transaction.
- *
- * @param[in] tx
- * Pointer to transaction structure.
- * @param[out] title
- * Title output.
- * @param[out] text
- * Text output.
- * @param[in] step
- * current step to display.
- *
- * @return true if there is content, false otherwise.
- *
- */
-bool htlc_lock_type_display(transaction_t *tx, char title[], char text[], uint16_t step);
diff --git a/src/ui/transactions/htlc_refund_display.c b/src/ui/transactions/htlc_refund_display.c
deleted file mode 100644
index 02986d93..00000000
--- a/src/ui/transactions/htlc_refund_display.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#include
-#include "htlc_refund_display.h"
-#include "types.h"
-#include "constants.h"
-#include "../../common/buffer.h"
-#include "../../common/format.h"
-#include "../../common/base58.h"
-
-bool htlc_refund_type_display(transaction_t *tx, char title[], char text[], uint16_t step) {
- switch (step) {
- case 0: {
- // Lock Transaction Id
- snprintf(title, MAX_TITLE_LEN, "%s", "Lock ID");
- format_hex(tx->core_asset.Htlc_refund.lockId, HASH_32_LEN, text, MAX_TEXT_LEN);
- break;
- }
- case 1: {
- // Fee
- snprintf(title, MAX_TITLE_LEN, "%s", "Fee");
- format_amount(text,
- MAX_TEXT_LEN,
- tx->fee,
- EXPONENT_SMALLEST_UNIT,
- TICKER_DEFAULT,
- sizeof(TICKER_DEFAULT));
- break;
- }
- default: {
- return false;
- }
- }
-
- return true;
-}
diff --git a/src/ui/transactions/htlc_refund_display.h b/src/ui/transactions/htlc_refund_display.h
deleted file mode 100644
index 8ad15fb8..00000000
--- a/src/ui/transactions/htlc_refund_display.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#pragma once
-
-#include
-#include "../../transaction/types.h"
-#include "../ctx.h"
-
-/**
- * Produce content for specific transaction.
- *
- * @param[in] tx
- * Pointer to transaction structure.
- * @param[out] title
- * Title output.
- * @param[out] text
- * Text output.
- * @param[in] step
- * current step to display.
- *
- * @return true if there is content, false otherwise.
- *
- */
-bool htlc_refund_type_display(transaction_t *tx, char title[], char text[], uint16_t step);
diff --git a/src/ui/transactions/ipfs_display.c b/src/ui/transactions/ipfs_display.c
index 9ca4619f..77ca2270 100644
--- a/src/ui/transactions/ipfs_display.c
+++ b/src/ui/transactions/ipfs_display.c
@@ -5,19 +5,27 @@
* 4.0 International License.
*****************************************************************************/
-#include
-#include "ipfs_display.h"
-#include "types.h"
+#include "ui/transactions/ipfs_display.h"
+
+#include // bool
+#include // uint*_t
+#include // snprintf
+
+#include "base58.h"
+#include "buffer.h"
+#include "format.h"
+
#include "constants.h"
-#include "../../common/buffer.h"
-#include "../../common/format.h"
-#include "../../common/base58.h"
+
+#include "transaction/transaction_utils.h"
+#include "transaction/types.h"
+#include "ui/ctx.h"
bool ipfs_type_display(transaction_t *tx, char title[], char text[], uint16_t step) {
switch (step) {
case 0: {
// IPFS hash
- snprintf(title, MAX_TITLE_LEN, "%s", "Content ID");
+ snprintf(title, MAX_TITLE_LEN, "Content ID");
char encoded[100] = {0};
int base58_length = base58_encode(tx->core_asset.Ipfs.ipfs,
tx->core_asset.Ipfs.ipfs_length,
@@ -28,7 +36,7 @@ bool ipfs_type_display(transaction_t *tx, char title[], char text[], uint16_t st
}
case 1: {
// Fee
- snprintf(title, MAX_TITLE_LEN, "%s", "Fee");
+ snprintf(title, MAX_TITLE_LEN, "Fee");
format_amount(text,
MAX_TEXT_LEN,
tx->fee,
diff --git a/src/ui/transactions/ipfs_display.h b/src/ui/transactions/ipfs_display.h
index cf2d6aab..c510dec1 100644
--- a/src/ui/transactions/ipfs_display.h
+++ b/src/ui/transactions/ipfs_display.h
@@ -1,15 +1,9 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
#pragma once
-#include
-#include "../../transaction/types.h"
-#include "../ctx.h"
+#include // bool
+#include // uint*_t
+
+#include "transaction/types.h"
/**
* Produce content for specific transaction.
diff --git a/src/ui/transactions/multi_signature_registration_display.c b/src/ui/transactions/multi_signature_registration_display.c
deleted file mode 100644
index 7188dd84..00000000
--- a/src/ui/transactions/multi_signature_registration_display.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#include
-#include "multi_signature_registration_display.h"
-#include "types.h"
-#include "constants.h"
-#include "../../common/buffer.h"
-#include "../../common/format.h"
-
-bool multisignature_type_display(transaction_t *tx, char title[], char text[], uint16_t step) {
- // Public keys
- if (step < tx->core_asset.Multisignature.pkey_length) {
- snprintf(title,
- MAX_TITLE_LEN,
- "%s %d/%d",
- "PublicKey",
- step + 1,
- tx->core_asset.Multisignature.pkey_length);
- format_hex(&tx->core_asset.Multisignature.pkeys[PUBLIC_KEY_LEN * step],
- PUBLIC_KEY_LEN,
- text,
- MAX_TEXT_LEN);
- return true;
- }
-
- switch (step - tx->core_asset.Multisignature.pkey_length) {
- case 0: {
- // Minimum
- snprintf(title, MAX_TITLE_LEN, "%s", "Minimum");
- snprintf(text, MAX_TEXT_LEN, "%d", tx->core_asset.Multisignature.min);
- break;
- }
- case 1: {
- // Fee
- snprintf(title, MAX_TITLE_LEN, "%s", "Fee");
- format_amount(text,
- MAX_TEXT_LEN,
- tx->fee,
- EXPONENT_SMALLEST_UNIT,
- TICKER_DEFAULT,
- sizeof(TICKER_DEFAULT));
- break;
- }
- default: {
- return false;
- }
- }
-
- return true;
-}
diff --git a/src/ui/transactions/multi_signature_registration_display.h b/src/ui/transactions/multi_signature_registration_display.h
deleted file mode 100644
index 259fb4b0..00000000
--- a/src/ui/transactions/multi_signature_registration_display.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
-#pragma once
-
-#include
-#include "../../transaction/types.h"
-#include "../ctx.h"
-
-/**
- * Produce content for specific transaction.
- *
- * @param[in] tx
- * Pointer to transaction structure.
- * @param[out] title
- * Title output.
- * @param[out] text
- * Text output.
- * @param[in] step
- * current step to display.
- *
- * @return true if there is content, false otherwise.
- *
- */
-bool multisignature_type_display(transaction_t *tx, char title[], char text[], uint16_t step);
diff --git a/src/ui/transactions/transfer_display.c b/src/ui/transactions/transfer_display.c
index 2a197548..9d13f8ae 100644
--- a/src/ui/transactions/transfer_display.c
+++ b/src/ui/transactions/transfer_display.c
@@ -5,27 +5,35 @@
* 4.0 International License.
*****************************************************************************/
-#include
-#include "transfer_display.h"
-#include "types.h"
-#include "constants.h"
+#include "ui/transactions/transfer_display.h"
+
+#include // snprintf
+#include // uint*_t
+
+#include "buffer.h"
+#include "format.h"
+#include "read.h"
+
#include "address.h"
-#include "../../common/buffer.h"
-#include "../../common/format.h"
-#include "../../common/read.h"
+#include "constants.h"
+
+#include "transaction/transaction_utils.h"
+#include "transaction/types.h"
+#include "ui/ctx.h"
bool transfer_type_display(transaction_t *tx, char title[], char text[], uint16_t step) {
// transfers (amount + recipient)
uint16_t number_recipients = step / 2;
+
if (number_recipients < tx->core_asset.Transfer.transfers_length) {
uint16_t offset = number_recipients * (ADDRESS_HASH_LEN + 8);
+
if (step % 2 == 0) {
- // Recipient
+ // Prepare the recipient[n] screen
offset += 8;
snprintf(title,
MAX_TITLE_LEN,
- "%s %d/%d",
- "Address",
+ "Address %d/%d",
number_recipients + 1,
tx->core_asset.Transfer.transfers_length);
base58_encode_address(&tx->core_asset.Transfer.transfers[offset],
@@ -33,11 +41,10 @@ bool transfer_type_display(transaction_t *tx, char title[], char text[], uint16_
text,
MAX_TEXT_LEN);
} else {
- // Amount
+ // Prepare the amount[n] screen
snprintf(title,
MAX_TITLE_LEN,
- "%s %d/%d",
- "Amount",
+ "Amount %d/%d",
number_recipients + 1,
tx->core_asset.Transfer.transfers_length);
format_amount(text,
@@ -51,22 +58,17 @@ bool transfer_type_display(transaction_t *tx, char title[], char text[], uint16_
return true;
}
- switch (step - (tx->core_asset.Transfer.transfers_length * 2)) {
- case 0: {
- // Fee
- snprintf(title, MAX_TITLE_LEN, "%s", "Fee");
- format_amount(text,
- MAX_TEXT_LEN,
- tx->fee,
- EXPONENT_SMALLEST_UNIT,
- TICKER_DEFAULT,
- sizeof(TICKER_DEFAULT));
- break;
- }
- default: {
- return false;
- }
+ // Prepare the fee screen
+ if (step - (tx->core_asset.Transfer.transfers_length * 2) == 0) {
+ snprintf(title, MAX_TITLE_LEN, "Fee");
+ format_amount(text,
+ MAX_TEXT_LEN,
+ tx->fee,
+ EXPONENT_SMALLEST_UNIT,
+ TICKER_DEFAULT,
+ sizeof(TICKER_DEFAULT));
+ return true;
}
- return true;
+ return false;
}
diff --git a/src/ui/transactions/transfer_display.h b/src/ui/transactions/transfer_display.h
index eb397c2d..bd063056 100644
--- a/src/ui/transactions/transfer_display.h
+++ b/src/ui/transactions/transfer_display.h
@@ -1,15 +1,9 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
#pragma once
-#include
-#include "../../transaction/types.h"
-#include "../ctx.h"
+#include // bool
+#include // uint*_t
+
+#include "transaction/types.h"
/**
* Produce content for specific transaction.
diff --git a/src/ui/transactions/vote_display.c b/src/ui/transactions/vote_display.c
index a149aedf..d8fc7df3 100644
--- a/src/ui/transactions/vote_display.c
+++ b/src/ui/transactions/vote_display.c
@@ -5,87 +5,82 @@
* 4.0 International License.
*****************************************************************************/
-#include
+#include "ui/transactions/vote_display.h"
+
+#include // uint*_t
+#include // snprintf
#include
-#include "vote_display.h"
-#include "types.h"
+
+#include "base58.h"
+#include "buffer.h"
+#include "format.h"
+#include "read.h"
+
#include "constants.h"
-#include "../../transaction/types/vote.h"
-#include "../../common/buffer.h"
-#include "../../common/format.h"
-#include "../../common/read.h"
-#include "../../common/base58.h"
+#include "types.h"
+
+#include "transaction/transaction_utils.h"
+#include "transaction/types/vote.h"
+#include "ui/ctx.h"
bool vote_type_display(transaction_t *tx, char title[], char text[], uint16_t step) {
- // Votes
- uint16_t vote_number = step / 2;
- if (vote_number < tx->core_asset.Vote.vote_length) {
+ uint16_t vote_count = step / 2;
+
+ // Check if we are still in the voting phase
+ if (vote_count < tx->core_asset.Vote.vote_length) {
vote_deserialised_t asset = {0};
- vote_search(tx->core_asset.Vote.votes,
- vote_number,
- tx->core_asset.Vote.vote_length,
- &asset);
+ vote_search(tx->core_asset.Vote.votes, vote_count, tx->core_asset.Vote.vote_length, &asset);
+
if (step % 2 == 0) {
- char title_text[] = "Delegate (%d/%d)";
- if (vote_number >= 9) {
- strcpy(title_text, "Delegate(%d/%d)");
- }
+ // Prepare the vote[n] screen
snprintf(title,
MAX_TITLE_LEN,
- title_text,
- vote_number + 1,
+ "Vote (%d/%d)",
+ vote_count + 1,
tx->core_asset.Vote.vote_length);
-
snprintf(text, MAX_TEXT_LEN, "%.*s", asset.username_length, asset.username);
- return true;
} else {
- char title_text[] = "Vote %% (%d/%d)";
- if (vote_number >= 9) {
- strcpy(title_text, "Vote %%(%d/%d)");
- }
+ // Prepare the vote percentage[n] screen
snprintf(title,
MAX_TITLE_LEN,
- title_text,
- vote_number + 1,
+ "Vote %% (%d/%d)",
+ vote_count + 1,
tx->core_asset.Vote.vote_length);
format_percentage(text, MAX_TEXT_LEN, asset.percentage, 2);
- return true;
}
+
+ return true;
}
- switch (step - (tx->core_asset.Vote.vote_length * 2)) {
- case 0: {
- // Fee
- snprintf(title, MAX_TITLE_LEN, "%s", "Fee");
- format_amount(text,
- MAX_TEXT_LEN,
- tx->fee,
- EXPONENT_SMALLEST_UNIT,
- TICKER_DEFAULT,
- sizeof(TICKER_DEFAULT));
- break;
- }
- default: {
- return false;
- }
+ // Prepare the fee screen
+ if (step - (tx->core_asset.Vote.vote_length * 2) == 0) {
+ snprintf(title, MAX_TITLE_LEN, "Fee");
+ format_amount(text,
+ MAX_TEXT_LEN,
+ tx->fee,
+ EXPONENT_SMALLEST_UNIT,
+ TICKER_DEFAULT,
+ sizeof(TICKER_DEFAULT));
+ return true;
}
- return true;
+ return false;
}
bool vote_search(uint8_t *tx, uint8_t vote_number, uint8_t max_votes, vote_deserialised_t *asset) {
if (vote_number >= max_votes) {
return false;
}
- uint16_t offset = 0;
+
+ uint8_t *ptr = tx;
for (uint8_t i = 0; i < vote_number; i++) {
- uint8_t username_length = *(tx + offset);
- offset += username_length + 3;
+ uint8_t username_length = *ptr;
+ ptr += username_length + 3;
}
- asset->username_length = *(tx + offset);
- offset += 1;
- asset->username = tx + offset;
- offset += asset->username_length;
- asset->percentage = read_u16_le(tx, offset);
+ asset->username_length = *ptr++;
+ asset->username = ptr;
+ ptr += asset->username_length;
+ asset->percentage = read_u16_le(tx, ptr - tx);
+
return true;
}
diff --git a/src/ui/transactions/vote_display.h b/src/ui/transactions/vote_display.h
index c3368c88..f66968f1 100644
--- a/src/ui/transactions/vote_display.h
+++ b/src/ui/transactions/vote_display.h
@@ -1,15 +1,9 @@
-/*****************************************************************************
- * Copyright (c) Solar Network
- *
- * This work is licensed under a Creative Commons Attribution-NoDerivatives
- * 4.0 International License.
- *****************************************************************************/
-
#pragma once
-#include
-#include "../../transaction/types.h"
-#include "../ctx.h"
+#include // bool
+#include // uint*_t
+
+#include "transaction/types.h"
/**
* Produce content for specific transaction.
diff --git a/src/ui/ui_utils.c b/src/ui/ui_utils.c
new file mode 100644
index 00000000..235921c8
--- /dev/null
+++ b/src/ui/ui_utils.c
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ * Copyright (c) Solar Network
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ *****************************************************************************
+ *
+ * This work is licensed under a Creative Commons Attribution-NoDerivatives
+ * 4.0 International License.
+ *
+ * This software also incorporates work covered by the following copyright
+ * and permission notice:
+ *
+ * Ledger App Boilerplate.
+ * (c) 2023 Ledger SAS.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *****************************************************************************/
+
+#include "ui/ui_utils.h"
+
+#include // size_t
+#include // uint*_t
+#include // bool
+#include // strlen
+
+#include "bolos_target.h"
+
+#if defined(TARGET_NANOS) // Estimate amount/fee line pixel count for the Nano S.
+
+// copied from:
+// https://github.com/LedgerHQ/nanos-secure-sdk/blob/master/lib_ux/include/ux_layout_paging_compute.h#L8
+#define PIXEL_PER_LINE 114
+
+// extern from:
+// https://github.com/LedgerHQ/nanos-secure-sdk/blob/master/lib_ux/src/ux_layout_paging_compute.c#L20-#L117
+extern const char nanos_characters_width[96];
+
+// adapted from:
+// https://github.com/LedgerHQ/nanos-secure-sdk/blob/master/lib_ux/src/ux_layout_paging_compute.c#L147-#L175
+static uint32_t calculate_pixels(char *text, size_t text_length) {
+ char current_char;
+ uint32_t line_width = 0;
+
+ while (text_length--) {
+ current_char = *text;
+ line_width += (nanos_characters_width[current_char - 0x20] >> 0x04) & 0x0F;
+ text++;
+ }
+
+ return line_width;
+}
+
+#define GET_TICKER_LINE_BREAK(num_str) \
+ (((calculate_pixels((num_str), strlen(num_str))) >= ((PIXEL_PER_LINE) - (1))) ? ('\n') : (' '))
+
+#else // if NOT Nano S, Only return the space character.
+
+#define GET_TICKER_LINE_BREAK(num_str) ((void) (num_str), (' '))
+
+#endif
+
+void unpad_amount(char *amount, size_t len, size_t padding) {
+ char *ptr = amount + len - 1;
+ while (*ptr == '0' && *(ptr - padding) != '.') {
+ *ptr-- = 0;
+ }
+}
+
+char get_ticker_line_break(char *num_str) {
+ return GET_TICKER_LINE_BREAK(num_str);
+}
diff --git a/src/ui/ui_utils.h b/src/ui/ui_utils.h
new file mode 100644
index 00000000..da689673
--- /dev/null
+++ b/src/ui/ui_utils.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include // size_t
+
+/**
+ * Remove trailing zeros up to the decimal + padding.
+ *
+ * @param[in] amount
+ * Pointer to amount string.
+ * @param[in] len
+ * Length of amount string.
+ * @param[in] padding
+ * Length of zero padding to keep.
+ *
+ */
+void unpad_amount(char *amount, size_t len, size_t padding);
+
+/**
+ * Determine if a new page should be used for ticker display.
+ *
+ * (e.g., avoid `123456789012345678 / 9.00 SXP` being misread as `9.00 SXP`)
+ *
+ * @param[in] num_str
+ * Pointer to formatted number string.
+ *
+ * @return new line character if needed for Nano S, otherwise a space character.
+ *
+ */
+char get_ticker_line_break(char *num_str);
diff --git a/tests/functional/README.md b/tests/functional/README.md
index 44b9edb6..ace569a3 100644
--- a/tests/functional/README.md
+++ b/tests/functional/README.md
@@ -1,42 +1,73 @@
-# Functional Tests
+# How to use the Ragger test framework
-> :point_right: Every path on this document assumes you are at the root of the repository.
+This framework allows testing the application on the Speculos emulator or on a real device using LedgerComm or LedgerWallet
-These tests are implemented in Python and can be executed either using the
-[Speculos](https://github.com/LedgerHQ/speculos) emulator or a Ledger Nano S/X.
-Python dependencies are listed in [requirements.txt](requirements.txt), install
-them using [pip](https://pypi.org/project/pip/)
+## Quickly get started with Ragger and Speculos
-```shell
-pip install --extra-index-url https://test.pypi.org/simple/ -r tests/functional/requirements.txt
+### Install ragger and dependencies
+
+```
+pip install --extra-index-url https://test.pypi.org/simple/ -r requirements.txt
+sudo apt-get update && sudo apt-get install qemu-user-static
```
-> The `--extra-index-url` parameter helps fetch the latest version of Speculos.
+### Compile the application
-## Manual (Speculos GUI)
+The application to test must be compiled for all required devices.
+You can use for this the container `ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite`:
+```
+docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest
+cd # replace with the name of your app, (eg boilerplate)
+docker run --user "$(id -u)":"$(id -g)" --rm -ti -v "$(realpath .):/app" --privileged -v "/dev/bus/usb:/dev/bus/usb" ledger-app-builder-lite:latest
+make clean && make BOLOS_SDK=$_SDK # replace with one of [NANOS, NANOX, NANOSP, STAX]
+exit
+```
-The `--manual` parameter is used to launch the Speculos GUI via command line and is offered as a convenient alternative to opening Speculos separately.
+### Run a simple test using the Speculos emulator
-```shell
-pytest tests/functional/ --manual
+You can use the following command to get your first experience with Ragger and Speculos
```
+pytest -v --tb=short --device nanox --display
+```
+Or you can refer to the section `Available pytest options` to configure the options you want to use
-## Headless (Speculos Backend)
-The `--headless` parameter is used to run functional tests using the Speculos backend where button presses will be handled automatically.
+### Run a simple test using a real device
-```shell
-pytest tests/functional/ --headless
+The application to test must be loaded and started on a Ledger device plugged in USB.
+You can use for this the container `ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite`:
+```
+docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest
+cd app-/ # replace with the name of your app, (eg boilerplate)
+docker run --user "$(id -u)":"$(id -g)" --rm -ti -v "$(realpath .):/app" --privileged -v "/dev/bus/usb:/dev/bus/usb" ledger-app-builder-lite:latest
+make clean && make BOLOS_SDK=$_SDK load # replace with one of [NANOS, NANOX, NANOSP, STAX]
+exit
```
-## Launch with your Nano S/X/SPlus
+You can use the following command to get your first experience with Ragger and Ledgerwallet on a NANOX.
+Make sure that the device is plugged, unlocked, and that the tested application is open.
+```
+pytest -v --tb=short --device nanox --backend ledgerwallet
+```
+Or you can refer to the section `Available pytest options` to configure the options you want to use
+
+
+## Available pytest options
-To run the tests on your Ledger Nano S/X/SPlus, make sure you have the Solar application installed (see
-[this page](https://developers.ledger.com/docs/nano-app/load/) for installing an
-application on a Nano S) and opened on the device, and the device connected
-through USB, without any other software interacting with it. Then run:
+Standard useful pytest options
+```
+ -v formats the test summary in a readable way
+ -s enable logs for successful tests, on Speculos it will enable app logs if compiled with DEBUG=1
+ -k only run the tests that contain in their names
+ --tb=short in case of errors, formats the test traceback in a readable way
+```
-```shell
-pytest tests/functional/ --hid
+Custom pytest options
+```
+ --device run the test on the specified device [nanos,nanox,nanosp,stax,all]. This parameter is mandatory
+ --backend run the tests against the backend [speculos, ledgercomm, ledgerwallet]. Speculos is the default
+ --display on Speculos, enables the display of the app screen using QT
+ --golden_run on Speculos, screen comparison functions will save the current screen instead of comparing
+ --log_apdu_file log all apdu exchanges to the file in parameter. The previous file content is erased
```
diff --git a/tests/functional/client/__init__.py b/tests/functional/application_client/__init__.py
similarity index 100%
rename from tests/functional/client/__init__.py
rename to tests/functional/application_client/__init__.py
diff --git a/tests/functional/application_client/py.typed b/tests/functional/application_client/py.typed
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/functional/application_client/solar_command_sender.py b/tests/functional/application_client/solar_command_sender.py
new file mode 100644
index 00000000..95b05001
--- /dev/null
+++ b/tests/functional/application_client/solar_command_sender.py
@@ -0,0 +1,202 @@
+from enum import IntEnum
+from typing import Generator, List, Optional, Union
+from contextlib import contextmanager
+
+from application_client.solar_transaction import Transaction
+
+# from application_client.solar_utils import bip32_path_from_string
+
+from ragger.backend.interface import BackendInterface, RAPDU
+from ragger.bip import pack_derivation_path
+
+
+MAX_APDU_LEN: int = 255
+
+CLA: int = 0xE0
+
+
+class P1(IntEnum):
+ # Parameter 1 for first APDU number.
+ P1_START = 0x00
+ # Parameter 1 for maximum APDU number.
+ P1_MAX = 0x03
+ # Parameter 1 for screen confirmation for GET_PUBLIC_KEY.
+ P1_CONFIRM = 0x01
+
+
+class P2(IntEnum):
+ # Parameter 2 for last APDU to receive.
+ P2_LAST = 0x00
+ # Parameter 2 for more APDU to receive.
+ P2_MORE = 0x80
+
+
+class InsType(IntEnum):
+ GET_APP_NAME = 0xA1
+ GET_VERSION = 0xA2
+ GET_PUBLIC_KEY = 0xB1
+ GET_ADDRESS = 0xB2
+ SIGN_MESSAGE = 0xC1
+ SIGN_TX = 0xC2
+
+
+class Errors(IntEnum):
+ SW_DENY = 0x6985
+ SW_WRONG_P1P2 = 0x6A86
+ SW_WRONG_DATA_LENGTH = 0x6A87
+ SW_INS_NOT_SUPPORTED = 0x6D00
+ SW_CLA_NOT_SUPPORTED = 0x6E00
+ SW_WRONG_RESPONSE_LENGTH = 0xB000
+ SW_DISPLAY_BIP32_PATH_FAIL = 0xB001
+ SW_DISPLAY_ADDRESS_FAIL = 0xB002
+ SW_DISPLAY_AMOUNT_FAIL = 0xB003
+ SW_WRONG_TX_LENGTH = 0xB004
+ SW_TX_PARSING_FAIL = 0xB005
+ SW_TX_HASH_FAIL = 0xB006
+ SW_BAD_STATE = 0xB007
+ SW_SIGNATURE_FAIL = 0xB008
+
+
+def split_message(message: bytes, max_size: int) -> List[bytes]:
+ return [message[x : x + max_size] for x in range(0, len(message), max_size)]
+
+
+class SolarCommandSender:
+ def __init__(self, backend: BackendInterface) -> None:
+ self.backend = backend
+
+ def serialise(
+ self,
+ cla: int,
+ ins: Union[int, IntEnum],
+ p1: int = 0,
+ p2: int = 0,
+ data: bytes = b"",
+ ) -> bytes:
+
+ ins = cast(int, ins.value) if isinstance(ins, IntEnum) else cast(int, ins)
+
+ header: bytes = struct.pack(
+ "BBBBB", cla, ins, p1, p2, len(data)
+ ) # add Lc to APDU header
+
+ if self.debug:
+ logging.info("header: %s", header.hex())
+ logging.info("data: %s", data.hex())
+
+ return header + data
+
+ def get_app_and_version(self) -> RAPDU:
+ return self.backend.exchange(
+ cla=0xB0, # specific CLA for BOLOS
+ ins=0x01, # specific INS for get_app_and_version
+ p1=P1.P1_START,
+ p2=P2.P2_LAST,
+ data=b"",
+ )
+
+ def get_version(self) -> RAPDU:
+ return self.backend.exchange(
+ cla=CLA, ins=InsType.GET_VERSION, p1=P1.P1_START, p2=P2.P2_LAST, data=b""
+ )
+
+ def get_app_name(self) -> RAPDU:
+ return self.backend.exchange(
+ cla=CLA, ins=InsType.GET_APP_NAME, p1=P1.P1_START, p2=P2.P2_LAST, data=b""
+ )
+
+ # def get_public_key(self, path: str) -> RAPDU:
+ def get_public_key(self, path: str, display: int = 0, chaincode: int = 0) -> RAPDU:
+ return self.backend.exchange(
+ cla=CLA,
+ ins=InsType.GET_PUBLIC_KEY,
+ p1=display,
+ p2=chaincode,
+ data=pack_derivation_path(path),
+ )
+
+ @contextmanager
+ def get_public_key_with_confirmation(self, path: str, chaincode: int = 0) -> RAPDU:
+ with self.backend.exchange_async(
+ cla=CLA,
+ ins=InsType.GET_PUBLIC_KEY,
+ p1=P1.P1_CONFIRM,
+ p2=chaincode,
+ data=pack_derivation_path(path),
+ ) as response:
+ yield response
+
+ def get_address(self, path: str, display: int = 0, network: int = 0) -> RAPDU:
+ return self.backend.exchange(
+ cla=CLA,
+ ins=InsType.GET_ADDRESS,
+ p1=display,
+ p2=network,
+ data=pack_derivation_path(path),
+ )
+
+ @contextmanager
+ def get_address_with_confirmation(self, path: str, network: int = 0) -> RAPDU:
+ with self.backend.exchange_async(
+ cla=CLA,
+ ins=InsType.GET_ADDRESS,
+ p1=P1.P1_CONFIRM,
+ p2=network,
+ data=pack_derivation_path(path),
+ ) as response:
+ yield response
+
+ @contextmanager
+ def sign_message(self, path: str, message: str) -> RAPDU:
+ msg: bytes = b"".join(
+ [len(message).to_bytes(2, byteorder="little"), bytes(message, "ascii")]
+ )
+
+ self.backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_MESSAGE,
+ p1=P1.P1_START,
+ p2=P2.P2_MORE,
+ data=pack_derivation_path(path),
+ )
+ chunks = split_message(msg, MAX_APDU_LEN)
+ idx: int = P1.P1_START + 1
+
+ for chunk in chunks[:-1]:
+ self.backend.exchange(
+ cla=CLA, ins=InsType.SIGN_MESSAGE, p1=idx, p2=P2.P2_MORE, data=chunk
+ )
+ idx += 1
+
+ with self.backend.exchange_async(
+ cla=CLA, ins=InsType.SIGN_MESSAGE, p1=idx, p2=P2.P2_LAST, data=chunks[-1]
+ ) as response:
+ yield response
+
+ @contextmanager
+ def sign_transaction(self, path: str, transaction: Transaction) -> RAPDU:
+ tx: bytes = transaction.serialise()
+
+ self.backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START,
+ p2=P2.P2_MORE,
+ data=pack_derivation_path(path),
+ )
+ chunks = split_message(tx, MAX_APDU_LEN)
+ idx: int = P1.P1_START + 1
+
+ for chunk in chunks[:-1]:
+ self.backend.exchange(
+ cla=CLA, ins=InsType.SIGN_TX, p1=idx, p2=P2.P2_MORE, data=chunk
+ )
+ idx += 1
+
+ with self.backend.exchange_async(
+ cla=CLA, ins=InsType.SIGN_TX, p1=idx, p2=P2.P2_LAST, data=chunks[-1]
+ ) as response:
+ yield response
+
+ def get_async_response(self) -> Optional[RAPDU]:
+ return self.backend.last_async_response
diff --git a/tests/functional/application_client/solar_response_unpacker.py b/tests/functional/application_client/solar_response_unpacker.py
new file mode 100644
index 00000000..74c7739d
--- /dev/null
+++ b/tests/functional/application_client/solar_response_unpacker.py
@@ -0,0 +1,91 @@
+from typing import Tuple
+from struct import unpack
+
+# remainder, data_len, data
+def pop_sized_buf_from_buffer(buffer:bytes, size:int) -> Tuple[bytes, bytes]:
+ return buffer[size:], buffer[0:size]
+
+# remainder, data_len, data
+def pop_size_prefixed_buf_from_buf(buffer:bytes) -> Tuple[bytes, int, bytes]:
+ data_len = buffer[0]
+ return buffer[1+data_len:], data_len, buffer[1:data_len+1]
+
+# Unpack from response:
+# response = app_name (var)
+def unpack_get_app_name_response(response: bytes) -> str:
+ return response.decode("ascii")
+
+# Unpack from response:
+# response = MAJOR (1)
+# MINOR (1)
+# PATCH (1)
+def unpack_get_version_response(response: bytes) -> Tuple[int, int, int]:
+ assert len(response) == 3
+ major, minor, patch = unpack("BBB", response)
+ return (major, minor, patch)
+
+# Unpack from response:
+# response = format_id (1)
+# app_name_raw_len (1)
+# app_name_raw (var)
+# version_raw_len (1)
+# version_raw (var)
+# unused_len (1)
+# unused (var)
+def unpack_get_app_and_version_response(response: bytes) -> Tuple[str, str]:
+ response, _ = pop_sized_buf_from_buffer(response, 1)
+ response, _, app_name_raw = pop_size_prefixed_buf_from_buf(response)
+ response, _, version_raw = pop_size_prefixed_buf_from_buf(response)
+ response, _, _ = pop_size_prefixed_buf_from_buf(response)
+
+ assert len(response) == 0
+
+ return app_name_raw.decode("ascii"), version_raw.decode("ascii")
+
+# Unpack from response:
+# response = pub_key_len (1)
+# pub_key (var)
+def unpack_get_public_key_response(response: bytes) -> Tuple[int, bytes]:
+ response, pub_key_len, pub_key = pop_size_prefixed_buf_from_buf(response)
+
+ assert pub_key_len == 33
+ assert len(response) == 0
+
+ return pub_key_len, pub_key
+
+# Unpack from response:
+# response = pub_key_len (1)
+# pub_key (var)
+# chain_code_len (1)
+# chain_code (var)
+def unpack_get_public_key_chaincode_response(response: bytes) -> Tuple[int, bytes, int, bytes]:
+ response, pub_key_len, pub_key = pop_size_prefixed_buf_from_buf(response)
+ response, chain_code_len, chain_code = pop_size_prefixed_buf_from_buf(response)
+
+ assert pub_key_len == 33
+ assert chain_code_len == 32
+ assert len(response) == 0
+
+ return pub_key_len, pub_key, chain_code_len, chain_code
+
+# Unpack from response:
+# response = address_len (1)
+# address (var)
+def unpack_get_address_response(response: bytes) -> Tuple[int, str]:
+ response, address_len, address = pop_size_prefixed_buf_from_buf(response)
+
+ assert address_len == 34
+
+ return address_len, address
+
+# Unpack from response:
+# response = der_sig_len (1)
+# der_sig (var)
+# v (1)
+def unpack_sign_tx_response(response: bytes) -> Tuple[int, bytes, int]:
+ response, der_sig_len, der_sig = pop_size_prefixed_buf_from_buf(response)
+ response, v = pop_sized_buf_from_buffer(response, 1)
+
+ assert len(response) == 0
+
+ return der_sig_len, der_sig, int.from_bytes(v, byteorder='big')
diff --git a/tests/functional/client/transaction.py b/tests/functional/application_client/solar_transaction.py
similarity index 93%
rename from tests/functional/client/transaction.py
rename to tests/functional/application_client/solar_transaction.py
index 99147bb5..4ef2ae11 100644
--- a/tests/functional/client/transaction.py
+++ b/tests/functional/application_client/solar_transaction.py
@@ -1,6 +1,6 @@
from typing import Union
-from client.utils import write_varint, UINT64_MAX, UINT32_MAX, UINT16_MAX, UINT8_MAX
+from application_client.solar_utils import write_varint, UINT64_MAX, UINT32_MAX, UINT16_MAX, UINT8_MAX
class TransactionError(Exception):
@@ -33,7 +33,7 @@ def __init__(
self.startingByte: int = startingByte
if not (0 <= self.network <= UINT8_MAX):
- raise TransactionError(f"Bad netowrk: '{self.network}'!")
+ raise TransactionError(f"Bad network: '{self.network}'!")
if not (0 <= self.version <= UINT8_MAX):
raise TransactionError(f"Bad version: '{self.version}'!")
diff --git a/tests/functional/client/utils.py b/tests/functional/application_client/solar_utils.py
similarity index 77%
rename from tests/functional/client/utils.py
rename to tests/functional/application_client/solar_utils.py
index 01a5e76a..efd1312b 100644
--- a/tests/functional/client/utils.py
+++ b/tests/functional/application_client/solar_utils.py
@@ -17,9 +17,12 @@ def bip32_path_from_string(path: str) -> List[bytes]:
if "m" in splitted_path and splitted_path[0] == "m":
splitted_path = splitted_path[1:]
- return [int(p).to_bytes(4, byteorder="big") if "'" not in p
- else (0x80000000 | int(p[:-1])).to_bytes(4, byteorder="big")
- for p in splitted_path]
+ return [
+ int(p).to_bytes(4, byteorder="big")
+ if "'" not in p
+ else (0x80000000 | int(p[:-1])).to_bytes(4, byteorder="big")
+ for p in splitted_path
+ ]
def write_varint(n: int) -> bytes:
@@ -38,8 +41,7 @@ def write_varint(n: int) -> bytes:
raise ValueError(f"Can't write to varint: '{n}'!")
-def read_varint(buf: BytesIO,
- prefix: Optional[bytes] = None) -> int:
+def read_varint(buf: BytesIO, prefix: Optional[bytes] = None) -> int:
b: bytes = prefix if prefix else buf.read(1)
if not b:
@@ -59,14 +61,14 @@ def read(buf: BytesIO, size: int) -> bytes:
b: bytes = buf.read(size)
if len(b) < size:
- raise ValueError(f"Cant read {size} bytes in buffer!")
+ raise ValueError(f"Can't read {size} bytes in buffer!")
return b
-def read_uint(buf: BytesIO,
- bit_len: int,
- byteorder: Literal['big', 'little'] = 'little') -> int:
+def read_uint(
+ buf: BytesIO, bit_len: int, byteorder: Literal["big", "little"] = "little"
+) -> int:
size: int = bit_len // 8
b: bytes = buf.read(size)
diff --git a/tests/functional/client/client_interface.py b/tests/functional/client/client_interface.py
deleted file mode 100644
index 4ea91a10..00000000
--- a/tests/functional/client/client_interface.py
+++ /dev/null
@@ -1,106 +0,0 @@
-from abc import ABCMeta, abstractmethod
-
-from speculos.client import SpeculosClient, ApduException
-from ledgercomm import Transport
-
-
-class ClientInterface(metaclass=ABCMeta):
- @abstractmethod
- def apdu_exchange_with_buttons(self, cla, ins, p1, p2, cdata, n_screens):
- ...
-
- @abstractmethod
- def apdu_exchange_raw_with_buttons(self, raw, n_screens):
- ...
-
- @abstractmethod
- def apdu_exchange_raw(self, raw):
- ...
-
- @abstractmethod
- def apdu_exchange(self, cla, ins, p1, p2, cdata):
- ...
-
- @abstractmethod
- def start(self):
- ...
-
- @abstractmethod
- def close(self):
- ...
-
-
-class Speculos(ClientInterface):
- def __init__(self, file_path: str, args, automatic) -> None:
- self.client = SpeculosClient(app=file_path, args=args)
- self.automatic = automatic
-
- def apdu_exchange_with_buttons(self, cla, ins, p1, p2, cdata, n_screens):
- with self.client.apdu_exchange_nowait(
- cla=cla, ins=ins, p1=p1, p2=p2, data=cdata
- ) as exchange:
- if self.automatic:
- for _ in range(n_screens):
- self.client.press_and_release("right")
- # Approve
- self.client.press_and_release("both")
- return exchange.receive()
-
- def apdu_exchange_raw_with_buttons(self, raw, n_screens):
- return self.apdu_exchange_with_buttons(
- cla=raw[0] if len(raw) > 0 else b"",
- ins=raw[1] if len(raw) > 1 else b"",
- p1=raw[2] if len(raw) > 2 else b"",
- p2=raw[3] if len(raw) > 3 else b"",
- cdata=raw[5:] if len(raw) > 5 else b"",
- n_screens=n_screens,
- )
-
- def apdu_exchange_raw(self, raw):
- return self.client._apdu_exchange(
- bytes.fromhex(raw) if isinstance(raw, str) else raw
- )
-
- def apdu_exchange(self, cla, ins, p1, p2, cdata):
- return self.client.apdu_exchange(cla=cla, ins=ins, p1=p1, p2=p2, data=cdata)
-
- def start(self):
- self.client.start()
-
- def close(self):
- self.client.stop()
-
-
-class Ledgercomm(ClientInterface):
- def __init__(self) -> None:
- self.transport = Transport(interface="hid", debug=True)
-
- def apdu_exchange_with_buttons(self, cla, ins, p1, p2, cdata, n_screens):
- return self.apdu_exchange(cla, ins, p1, p2, cdata)
-
- def apdu_exchange_raw_with_buttons(self, raw, n_screens):
- return self.apdu_exchange_raw(raw)
-
- def apdu_exchange_raw(self, raw):
- sw, response = self.transport.exchange_raw(raw)
-
- if sw != 0x9000:
- raise ApduException(sw=sw, data=response)
-
- return response
-
- def apdu_exchange(self, cla, ins, p1, p2, cdata):
- sw, response = self.transport.exchange(
- cla=cla, ins=ins, p1=p1, p2=p2, cdata=cdata
- )
-
- if sw != 0x9000:
- raise ApduException(sw=sw, data=response)
-
- return response
-
- def start(self):
- pass
-
- def close(self):
- pass
diff --git a/tests/functional/client/cmd.py b/tests/functional/client/cmd.py
deleted file mode 100644
index e289b99c..00000000
--- a/tests/functional/client/cmd.py
+++ /dev/null
@@ -1,196 +0,0 @@
-import struct
-from typing import Tuple
-
-from client.client_interface import ClientInterface
-from speculos.client import ApduException
-
-from client.cmd_builder import CommandBuilder, InsType
-from client.exception import DeviceException
-from client.transaction import Transaction
-
-
-class Command:
- def __init__(self, transport: ClientInterface, debug: bool = False) -> None:
- self.transport = transport
- self.builder = CommandBuilder(debug=debug)
- self.debug = debug
-
- def get_app_and_version(self) -> Tuple[str, str]:
- try:
- response = self.transport.apdu_exchange_raw(
- self.builder.get_app_and_version()
- ) # type: int, bytes
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=0x01)
-
- # response = format_id (1) ||
- # app_name_len (1) ||
- # app_name (var) ||
- # version_len (1) ||
- # version (var) ||
- offset: int = 0
-
- format_id: int = response[offset]
- offset += 1
- app_name_len: int = response[offset]
- offset += 1
- app_name: str = response[offset : offset + app_name_len].decode("ascii")
- offset += app_name_len
- version_len: int = response[offset]
- offset += 1
- version: str = response[offset : offset + version_len].decode("ascii")
- offset += version_len
-
- return app_name, version
-
- def get_version(self) -> Tuple[int, int, int]:
- try:
- response = self.transport.apdu_exchange_raw(
- self.builder.get_version()
- ) # type: int, bytes
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_GET_VERSION)
-
- # response = MAJOR (1) || MINOR (1) || PATCH (1)
- assert len(response) == 3
-
- major, minor, patch = struct.unpack("BBB", response) # type: int, int, int
-
- return major, minor, patch
-
- def get_app_name(self) -> str:
- try:
- response = self.transport.apdu_exchange_raw(
- self.builder.get_app_name()
- ) # type: int, bytes
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_GET_APP_NAME)
-
- return response.decode("ascii")
-
- def get_public_key(
- self,
- bip32_path: str,
- display: int = False,
- chaincode: int = False,
- n_screens: int = 0,
- ) -> Tuple[bytes, bytes]:
- try:
- response = self.transport.apdu_exchange_raw_with_buttons(
- self.builder.get_public_key(
- bip32_path=bip32_path, display=display, chaincode=chaincode
- ),
- n_screens,
- ) # type: int, bytes
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_GET_PUBLIC_KEY)
-
- # response = pub_key_len (1) ||
- # pub_key (var) ||
- # chain_code_len (1) ||
- # chain_code (var)
- offset: int = 0
-
- pub_key_len: int = response[offset]
- offset += 1
- pub_key: bytes = response[offset : offset + pub_key_len]
- offset += pub_key_len
-
- chain_code_len: int = 0
- chain_code: bytes = {}
-
- if chaincode:
- chain_code_len = response[offset]
- offset += 1
- chain_code = response[offset : offset + chain_code_len]
- offset += chain_code_len
-
- assert len(response) == 1 + pub_key_len + (
- (1 + chain_code_len) if chaincode else 0
- )
-
- return pub_key, chain_code
-
- def get_address(
- self,
- bip32_path: str,
- display: int = False,
- network: int = 0,
- n_screens: int = 0,
- ) -> Tuple[bytes, bytes]:
- try:
- response = self.transport.apdu_exchange_raw_with_buttons(
- self.builder.get_address(
- bip32_path=bip32_path, display=display, network=network
- ),
- n_screens,
- ) # type: int, bytes
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_GET_ADDRESS)
-
- # response = address_len(1), address_string(34)
- offset: int = 0
-
- address_len: int = response[offset]
- offset += 1
- address: bytes = response[offset : offset + address_len]
- offset += address_len
-
- assert len(response) == 1 + address_len
-
- return address
-
- def sign_tx(
- self,
- bip32_path: str,
- transaction: Transaction,
- n_screens: int = 0,
- ) -> Tuple[int, bytes]:
- response: bytes = b""
-
- for is_last, chunk in self.builder.sign_tx(
- bip32_path=bip32_path, transaction=transaction
- ):
- try:
- response = self.transport.apdu_exchange_raw_with_buttons(
- chunk,
- n_screens if is_last else 0,
- ) # type: int, bytes
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_TX)
-
- # response = schnorr_sig_len (1) ||
- # schnorr_sig (var) ||
- # v (1)
-
- schnorr_sig: bytes = response
-
- assert len(response) == 64
-
- return schnorr_sig
-
- def sign_message(
- self, bip32_path: str, message: str, n_screens: int = 0
- ) -> Tuple[int, bytes]:
- response: bytes = b""
-
- for is_last, chunk in self.builder.sign_message(
- bip32_path=bip32_path, message=message
- ):
- try:
- response = self.transport.apdu_exchange_raw_with_buttons(
- chunk,
- n_screens if is_last else 0,
- ) # type: int, bytes
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_MESSAGE)
-
- # response = schnorr_sig_len (1) ||
- # schnorr_sig (var) ||
- # v (1)
-
- schnorr_sig: bytes = response
-
- assert len(response) == 64
-
- return schnorr_sig
diff --git a/tests/functional/client/cmd_builder.py b/tests/functional/client/cmd_builder.py
deleted file mode 100644
index 40ba3c11..00000000
--- a/tests/functional/client/cmd_builder.py
+++ /dev/null
@@ -1,304 +0,0 @@
-import enum
-import logging
-import struct
-from typing import List, Tuple, Union, Iterator, cast
-
-from client.transaction import Transaction
-from client.utils import bip32_path_from_string
-
-MAX_APDU_LEN: int = 255
-
-
-def chunkify(data: bytes, chunk_len: int) -> Iterator[Tuple[bool, bytes]]:
- size: int = len(data)
-
- if size <= chunk_len:
- yield True, data
- return
-
- remainder: int = size % chunk_len
- chunk: int = size // chunk_len if remainder == 0 else (size // chunk_len) + 1
- offset: int = 0
-
- for i in range(chunk - 1):
- yield False, data[offset : offset + chunk_len]
- offset += chunk_len
-
- yield True, data[offset:]
-
-
-class InsType(enum.IntEnum):
- INS_GET_APP_NAME = 0xA1
- INS_GET_VERSION = 0xA2
- INS_GET_PUBLIC_KEY = 0xB1
- INS_GET_ADDRESS = 0xB2
- INS_SIGN_MESSAGE = 0xC1
- INS_SIGN_TX = 0xC2
-
-
-class CommandBuilder:
- """APDU command builder for the Solar application.
-
- Parameters
- ----------
- debug: bool
- Whether you want to see logging or not.
-
- Attributes
- ----------
- debug: bool
- Whether you want to see logging or not.
-
- """
-
- CLA: int = 0xE0
-
- def __init__(self, debug: bool = False):
- """Init constructor."""
- self.debug = debug
-
- def serialise(
- self,
- cla: int,
- ins: Union[int, enum.IntEnum],
- p1: int = 0,
- p2: int = 0,
- cdata: bytes = b"",
- ) -> bytes:
- """Serialise the whole APDU command (header + data).
-
- Parameters
- ----------
- cla : int
- Instruction class: CLA (1 byte)
- ins : Union[int, IntEnum]
- Instruction code: INS (1 byte)
- p1 : int
- Instruction parameter 1: P1 (1 byte).
- p2 : int
- Instruction parameter 2: P2 (1 byte).
- cdata : bytes
- Bytes of command data.
-
- Returns
- -------
- bytes
- Bytes of a complete APDU command.
-
- """
- ins = cast(int, ins.value) if isinstance(ins, enum.IntEnum) else cast(int, ins)
-
- header: bytes = struct.pack(
- "BBBBB", cla, ins, p1, p2, len(cdata)
- ) # add Lc to APDU header
-
- if self.debug:
- logging.info("header: %s", header.hex())
- logging.info("cdata: %s", cdata.hex())
-
- return header + cdata
-
- def get_app_and_version(self) -> bytes:
- """Command builder for GET_APP_AND_VERSION (builtin in BOLOS SDK).
-
- Returns
- -------
- bytes
- APDU command for GET_APP_AND_VERSION.
-
- """
- return self.serialise(
- cla=0xB0, ins=0x01, p1=0x00, p2=0x00, cdata=b"" # specific CLA for BOLOS
- )
-
- def get_app_name(self) -> bytes:
- """Command builder for GET_APP_NAME.
-
- Returns
- -------
- bytes
- APDU command for GET_APP_NAME.
-
- """
- return self.serialise(
- cla=self.CLA, ins=InsType.INS_GET_APP_NAME, p1=0x00, p2=0x00, cdata=b""
- )
-
- def get_version(self) -> bytes:
- """Command builder for GET_VERSION.
-
- Returns
- -------
- bytes
- APDU command for GET_VERSION.
-
- """
- return self.serialise(
- cla=self.CLA, ins=InsType.INS_GET_VERSION, p1=0x00, p2=0x00, cdata=b""
- )
-
- def get_public_key(
- self, bip32_path: str, display: int = 0, chaincode: int = 0
- ) -> bytes:
- """Command builder for GET_PUBLIC_KEY.
-
- Parameters
- ----------
- bip32_path: str
- String representation of BIP32 path.
- display : bool
- Whether you want to display the public key on the device.
- chaincode : bool
- Whether you want to include the chain code in the response.
-
- Returns
- -------
- bytes
- APDU command for GET_PUBLIC_KEY.
-
- """
- bip32_paths: List[bytes] = bip32_path_from_string(bip32_path)
-
- cdata: bytes = b"".join(
- [len(bip32_paths).to_bytes(1, byteorder="big"), *bip32_paths]
- )
-
- return self.serialise(
- cla=self.CLA,
- ins=InsType.INS_GET_PUBLIC_KEY,
- p1=display,
- p2=chaincode,
- cdata=cdata,
- )
-
- def get_address(self, bip32_path: str, display: int = 0, network: int = 0) -> bytes:
- """Command builder for GET_ADDRESS.
-
- Parameters
- ----------
- bip32_path: str
- String representation of BIP32 path.
- display : bool
- Whether you want to display the public key on the device.
- network : bool
- Which network the publicKey should be encoded for.
-
- Returns
- -------
- bytes
- APDU command for GET_ADDRESS.
-
- """
- bip32_paths: List[bytes] = bip32_path_from_string(bip32_path)
-
- cdata: bytes = b"".join(
- [len(bip32_paths).to_bytes(1, byteorder="big"), *bip32_paths]
- )
-
- return self.serialise(
- cla=self.CLA,
- ins=InsType.INS_GET_ADDRESS,
- p1=display,
- p2=network,
- cdata=cdata,
- )
-
- def sign_message(
- self, bip32_path: str, message: str
- ) -> Iterator[Tuple[bool, bytes]]:
- """Command builder for INS_SIGN_TX.
-
- Parameters
- ----------
- bip32_path : str
- String representation of BIP32 path.
- message : str
- Message to be signed.
-
- Yields
- -------
- bytes
- APDU command chunk for INS_SIGN_MESSAGE.
-
- """
- bip32_paths: List[bytes] = bip32_path_from_string(bip32_path)
-
- cdata: bytes = b"".join(
- [len(bip32_paths).to_bytes(1, byteorder="big"), *bip32_paths]
- )
-
- yield False, self.serialise(
- cla=self.CLA, ins=InsType.INS_SIGN_MESSAGE, p1=0x00, p2=0x80, cdata=cdata
- )
-
- tx: bytes = b"".join(
- [len(message).to_bytes(2, byteorder="little"), bytes(message, "ascii")]
- )
-
- for i, (is_last, chunk) in enumerate(chunkify(tx, MAX_APDU_LEN)):
- if is_last:
- yield True, self.serialise(
- cla=self.CLA,
- ins=InsType.INS_SIGN_MESSAGE,
- p1=i + 1,
- p2=0x00,
- cdata=chunk,
- )
- return
- else:
- yield False, self.serialise(
- cla=self.CLA,
- ins=InsType.INS_SIGN_MESSAGE,
- p1=i + 1,
- p2=0x80,
- cdata=chunk,
- )
-
- def sign_tx(
- self, bip32_path: str, transaction: Transaction
- ) -> Iterator[Tuple[bool, bytes]]:
- """Command builder for INS_SIGN_TX.
-
- Parameters
- ----------
- bip32_path : str
- String representation of BIP32 path.
- transaction : Transaction
- Representation of the transaction to be signed.
-
- Yields
- -------
- bytes
- APDU command chunk for INS_SIGN_TX.
-
- """
- bip32_paths: List[bytes] = bip32_path_from_string(bip32_path)
-
- cdata: bytes = b"".join(
- [len(bip32_paths).to_bytes(1, byteorder="big"), *bip32_paths]
- )
-
- yield False, self.serialise(
- cla=self.CLA, ins=InsType.INS_SIGN_TX, p1=0x00, p2=0x80, cdata=cdata
- )
-
- tx: bytes = transaction.serialise()
-
- for i, (is_last, chunk) in enumerate(chunkify(tx, MAX_APDU_LEN)):
- if is_last:
- yield True, self.serialise(
- cla=self.CLA,
- ins=InsType.INS_SIGN_TX,
- p1=i + 1,
- p2=0x00,
- cdata=chunk,
- )
- return
- else:
- yield False, self.serialise(
- cla=self.CLA,
- ins=InsType.INS_SIGN_TX,
- p1=i + 1,
- p2=0x80,
- cdata=chunk,
- )
diff --git a/tests/functional/client/exception/__init__.py b/tests/functional/client/exception/__init__.py
deleted file mode 100644
index 4f791324..00000000
--- a/tests/functional/client/exception/__init__.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from .device_exception import DeviceException
-from .errors import (UnknownDeviceError,
- DenyError,
- WrongP1P2Error,
- WrongDataLengthError,
- InsNotSupportedError,
- ClaNotSupportedError,
- WrongResponseLengthError,
- DisplayBip32PathFailError,
- DisplayPublicKeyFailError,
- DisplayAmountFailError,
- WrongTxLengthError,
- TxParsingFailError,
- TxHashFail,
- BadStateError,
- SignatureFailError,
- OutOfOrderReqError,
- DisplayAddressFailError)
-
-__all__ = [
- "DeviceException",
- "DenyError",
- "UnknownDeviceError",
- "WrongP1P2Error",
- "WrongDataLengthError",
- "InsNotSupportedError",
- "ClaNotSupportedError",
- "WrongResponseLengthError",
- "DisplayBip32PathFailError",
- "DisplayPublicKeyFailError",
- "DisplayAmountFailError",
- "WrongTxLengthError",
- "TxParsingFailError",
- "TxHashFail",
- "BadStateError",
- "SignatureFailError",
- "OutOfOrderReqError",
- "DisplayAddressFailError"
-]
diff --git a/tests/functional/client/exception/device_exception.py b/tests/functional/client/exception/device_exception.py
deleted file mode 100644
index 160ae049..00000000
--- a/tests/functional/client/exception/device_exception.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import enum
-from typing import Dict, Any, Union
-
-from .errors import *
-
-
-class DeviceException(Exception): # pylint: disable=too-few-public-methods
- exc: Dict[int, Any] = {
- 0x6985: DenyError,
- 0x6A86: WrongP1P2Error,
- 0x6A87: WrongDataLengthError,
- 0x6D00: InsNotSupportedError,
- 0x6E00: ClaNotSupportedError,
- 0xB000: WrongResponseLengthError,
- 0xB001: DisplayBip32PathFailError,
- 0xB002: DisplayPublicKeyFailError,
- 0xB003: DisplayAmountFailError,
- 0xB004: WrongTxLengthError,
- 0xB005: TxParsingFailError,
- 0xB006: TxHashFail,
- 0xB007: BadStateError,
- 0xB008: SignatureFailError,
- 0xB009: OutOfOrderReqError,
- 0xB010: EncodeAddressFailError,
- 0xB011: DisplayAddressFailError,
- }
-
- def __new__(cls,
- error_code: int,
- ins: Union[int, enum.IntEnum, None] = None,
- message: str = ""
- ) -> Any:
- error_message: str = (f"Error in {ins!r} command"
- if ins else "Error in command")
-
- if error_code in DeviceException.exc:
- return DeviceException.exc[error_code](hex(error_code),
- error_message,
- message)
-
- return UnknownDeviceError(hex(error_code), error_message, message)
diff --git a/tests/functional/client/exception/errors.py b/tests/functional/client/exception/errors.py
deleted file mode 100644
index a16c778c..00000000
--- a/tests/functional/client/exception/errors.py
+++ /dev/null
@@ -1,67 +0,0 @@
-class UnknownDeviceError(Exception):
- pass
-
-
-class DenyError(Exception):
- pass
-
-
-class WrongP1P2Error(Exception):
- pass
-
-
-class WrongDataLengthError(Exception):
- pass
-
-
-class InsNotSupportedError(Exception):
- pass
-
-
-class ClaNotSupportedError(Exception):
- pass
-
-
-class WrongResponseLengthError(Exception):
- pass
-
-
-class DisplayBip32PathFailError(Exception):
- pass
-
-
-class DisplayPublicKeyFailError(Exception):
- pass
-
-
-class DisplayAmountFailError(Exception):
- pass
-
-
-class WrongTxLengthError(Exception):
- pass
-
-
-class TxParsingFailError(Exception):
- pass
-
-
-class TxHashFail(Exception):
- pass
-
-
-class BadStateError(Exception):
- pass
-
-
-class SignatureFailError(Exception):
- pass
-
-class OutOfOrderReqError(Exception):
- pass
-
-class DisplayAddressFailError(Exception):
- pass
-
-class EncodeAddressFailError(Exception):
- pass
diff --git a/tests/functional/conftest.py b/tests/functional/conftest.py
index 8442c9c4..909ec8bf 100644
--- a/tests/functional/conftest.py
+++ b/tests/functional/conftest.py
@@ -1,63 +1,15 @@
-from pathlib import Path
+from ragger.conftest import configuration
-import pytest
+###########################
+### CONFIGURATION START ###
+###########################
-from client.client_interface import Speculos, Ledgercomm
-from client.cmd import Command
+# You can configure optional parameters by overriding the value of ragger.configuration.OPTIONAL_CONFIGURATION
+# Please refer to ragger/conftest/configuration.py for their descriptions and accepted values
-SCRIPT_DIR = Path(__file__).absolute().parent
+#########################
+### CONFIGURATION END ###
+#########################
-
-def pytest_addoption(parser):
- parser.addoption("--hid", action="store_true")
- parser.addoption("--headless", action="store_true")
- parser.addoption("--manual", action="store_true")
-
-
-@pytest.fixture(scope="module")
-def sw_h_path():
- # path with tests
- conftest_folder_path: Path = Path(__file__).parent
- # sw.h should be in ../../src/sw.h
- sw_h_path = conftest_folder_path.parent.parent / "src" / "sw.h"
-
- if not sw_h_path.is_file():
- raise FileNotFoundError(f"Can't find sw.h: '{sw_h_path}'")
-
- return sw_h_path
-
-
-@pytest.fixture(scope="session")
-def hid(pytestconfig):
- return pytestconfig.getoption("hid")
-
-
-@pytest.fixture(scope="session")
-def headless(pytestconfig):
- return pytestconfig.getoption("headless")
-
-
-@pytest.fixture(scope="session")
-def manual(pytestconfig):
- return pytestconfig.getoption("manual")
-
-
-@pytest.fixture(scope="session")
-def cmd(hid, headless, manual):
- file_path = SCRIPT_DIR.parent.parent / "bin" / "app.elf"
- args = ["--model", "nanos", "--sdk", "2.1"]
- if headless:
- manual = False
- else:
- args.append("--display")
- args.append("qt")
-
- transport = (
- Ledgercomm()
- if hid
- else Speculos(file_path=str(file_path), args=args, automatic=not manual)
- )
- command = Command(transport=transport, debug=True)
- command.transport.start()
- yield command
- command.transport.close()
+# Pull all features from the base ragger conftest using the overridden configuration
+pytest_plugins = ("ragger.conftest.base_conftest", )
diff --git a/tests/functional/constants.py b/tests/functional/constants.py
new file mode 100644
index 00000000..4348e562
--- /dev/null
+++ b/tests/functional/constants.py
@@ -0,0 +1,7 @@
+
+NETWORK_MAINNET: int = 0x3F
+NETWORK_TESTNET: int = 0x1E
+NETWORKS: [int] = [NETWORK_MAINNET, NETWORK_TESTNET]
+
+PATH_MAINNET: str = "m/44'/3333'/0'/0/0"
+PATH_TESTNET: str = "m/44'/1'/0'/0/0"
diff --git a/tests/functional/requirements.txt b/tests/functional/requirements.txt
index 2b2c5e78..b5d9277b 100644
--- a/tests/functional/requirements.txt
+++ b/tests/functional/requirements.txt
@@ -1,4 +1,4 @@
-speculos
-pytest>=6.1.1,<7.0.0
-btclib
-ledgercomm[hid]
+pytest==7.3.1
+btclib==2023.2.3
+ragger[speculos]==1.11.4
+ragger[ledgerwallet]==1.11.4
diff --git a/tests/functional/setup.cfg b/tests/functional/setup.cfg
index c79fd882..7d0d7e30 100644
--- a/tests/functional/setup.cfg
+++ b/tests/functional/setup.cfg
@@ -8,10 +8,11 @@ disable = C0114, # missing-module-docstring
C0103, # invalid-name
R0801, # duplicate-code
R0913 # too-many-arguments
+max-line-length=100
extension-pkg-whitelist=hid
[pycodestyle]
-max-line-length = 90
+max-line-length = 100
[mypy-hid.*]
ignore_missing_imports = True
diff --git a/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00000.png b/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00000.png
new file mode 100644
index 00000000..0e647232
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00000.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00001.png b/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00001.png
new file mode 100644
index 00000000..94281378
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00001.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00002.png b/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00002.png
new file mode 100644
index 00000000..a1fffd45
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00002.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00003.png b/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00003.png
new file mode 100644
index 00000000..a16583ff
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00003.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00004.png b/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00004.png
new file mode 100644
index 00000000..66c411c2
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00004.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00005.png b/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00005.png
new file mode 100644
index 00000000..019b9bb0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_address_confirm_accepted/00005.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00000.png b/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00000.png
new file mode 100644
index 00000000..0e647232
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00000.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00001.png b/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00001.png
new file mode 100644
index 00000000..94281378
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00001.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00002.png b/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00002.png
new file mode 100644
index 00000000..a1fffd45
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00002.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00003.png b/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00003.png
new file mode 100644
index 00000000..a16583ff
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00003.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00004.png b/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00004.png
new file mode 100644
index 00000000..66c411c2
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00004.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00005.png b/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00005.png
new file mode 100644
index 00000000..9c7e7049
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00005.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00006.png b/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00006.png
new file mode 100644
index 00000000..019b9bb0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_address_confirm_refused/00006.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00000.png b/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00000.png
new file mode 100644
index 00000000..9710855b
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00000.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00001.png b/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00001.png
new file mode 100644
index 00000000..280b279c
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00001.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00002.png b/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00002.png
new file mode 100644
index 00000000..ac25c21e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00002.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00003.png b/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00003.png
new file mode 100644
index 00000000..5be04cc8
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00003.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00004.png b/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00004.png
new file mode 100644
index 00000000..ec00557e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00004.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00005.png b/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00005.png
new file mode 100644
index 00000000..66c411c2
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00005.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00006.png b/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00006.png
new file mode 100644
index 00000000..019b9bb0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_chaincode_confirm_accepted/00006.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00000.png b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00000.png
new file mode 100644
index 00000000..9710855b
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00000.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00001.png b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00001.png
new file mode 100644
index 00000000..280b279c
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00001.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00002.png b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00002.png
new file mode 100644
index 00000000..ac25c21e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00002.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00003.png b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00003.png
new file mode 100644
index 00000000..5be04cc8
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00003.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00004.png b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00004.png
new file mode 100644
index 00000000..ec00557e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00004.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00005.png b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00005.png
new file mode 100644
index 00000000..66c411c2
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00005.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00006.png b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00006.png
new file mode 100644
index 00000000..9c7e7049
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00006.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00007.png b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00007.png
new file mode 100644
index 00000000..019b9bb0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_confirm_refused/00007.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00000.png b/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00000.png
new file mode 100644
index 00000000..9710855b
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00000.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00001.png b/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00001.png
new file mode 100644
index 00000000..280b279c
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00001.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00002.png b/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00002.png
new file mode 100644
index 00000000..ac25c21e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00002.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00003.png b/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00003.png
new file mode 100644
index 00000000..5be04cc8
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00003.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00004.png b/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00004.png
new file mode 100644
index 00000000..ec00557e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00004.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00005.png b/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00005.png
new file mode 100644
index 00000000..66c411c2
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00005.png differ
diff --git a/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00006.png b/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00006.png
new file mode 100644
index 00000000..019b9bb0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_get_public_key_no_chaincode_confirm_accepted/00006.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00000.png b/tests/functional/snapshots/nanos/test_sign_message_long/00000.png
new file mode 100644
index 00000000..5caa4c03
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00000.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00001.png b/tests/functional/snapshots/nanos/test_sign_message_long/00001.png
new file mode 100644
index 00000000..adbeee1e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00001.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00002.png b/tests/functional/snapshots/nanos/test_sign_message_long/00002.png
new file mode 100644
index 00000000..da2f8099
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00002.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00003.png b/tests/functional/snapshots/nanos/test_sign_message_long/00003.png
new file mode 100644
index 00000000..15e5b124
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00003.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00004.png b/tests/functional/snapshots/nanos/test_sign_message_long/00004.png
new file mode 100644
index 00000000..28e37418
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00004.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00005.png b/tests/functional/snapshots/nanos/test_sign_message_long/00005.png
new file mode 100644
index 00000000..8f83b6a6
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00005.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00006.png b/tests/functional/snapshots/nanos/test_sign_message_long/00006.png
new file mode 100644
index 00000000..615310df
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00006.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00007.png b/tests/functional/snapshots/nanos/test_sign_message_long/00007.png
new file mode 100644
index 00000000..c5de1fde
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00007.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00008.png b/tests/functional/snapshots/nanos/test_sign_message_long/00008.png
new file mode 100644
index 00000000..5367d5b3
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00008.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00009.png b/tests/functional/snapshots/nanos/test_sign_message_long/00009.png
new file mode 100644
index 00000000..2022ea73
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00009.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00010.png b/tests/functional/snapshots/nanos/test_sign_message_long/00010.png
new file mode 100644
index 00000000..c4e69dcc
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00010.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00011.png b/tests/functional/snapshots/nanos/test_sign_message_long/00011.png
new file mode 100644
index 00000000..d8bac7bb
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00011.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00012.png b/tests/functional/snapshots/nanos/test_sign_message_long/00012.png
new file mode 100644
index 00000000..6098daa4
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00012.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00013.png b/tests/functional/snapshots/nanos/test_sign_message_long/00013.png
new file mode 100644
index 00000000..a7cedc93
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00013.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00014.png b/tests/functional/snapshots/nanos/test_sign_message_long/00014.png
new file mode 100644
index 00000000..3e3b15e6
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00014.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00015.png b/tests/functional/snapshots/nanos/test_sign_message_long/00015.png
new file mode 100644
index 00000000..b52c205c
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00015.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00016.png b/tests/functional/snapshots/nanos/test_sign_message_long/00016.png
new file mode 100644
index 00000000..825f1b40
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00016.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00017.png b/tests/functional/snapshots/nanos/test_sign_message_long/00017.png
new file mode 100644
index 00000000..07d12d32
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00017.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00018.png b/tests/functional/snapshots/nanos/test_sign_message_long/00018.png
new file mode 100644
index 00000000..8eb48bd4
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00018.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00019.png b/tests/functional/snapshots/nanos/test_sign_message_long/00019.png
new file mode 100644
index 00000000..2afb34eb
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00019.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00020.png b/tests/functional/snapshots/nanos/test_sign_message_long/00020.png
new file mode 100644
index 00000000..8525a8d9
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00020.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00021.png b/tests/functional/snapshots/nanos/test_sign_message_long/00021.png
new file mode 100644
index 00000000..1541f3eb
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00021.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00022.png b/tests/functional/snapshots/nanos/test_sign_message_long/00022.png
new file mode 100644
index 00000000..6a27c708
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00022.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00023.png b/tests/functional/snapshots/nanos/test_sign_message_long/00023.png
new file mode 100644
index 00000000..eb1f6ada
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00023.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00024.png b/tests/functional/snapshots/nanos/test_sign_message_long/00024.png
new file mode 100644
index 00000000..c2be7c6a
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00024.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00025.png b/tests/functional/snapshots/nanos/test_sign_message_long/00025.png
new file mode 100644
index 00000000..93132b22
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00025.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00026.png b/tests/functional/snapshots/nanos/test_sign_message_long/00026.png
new file mode 100644
index 00000000..fcd32146
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00026.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00027.png b/tests/functional/snapshots/nanos/test_sign_message_long/00027.png
new file mode 100644
index 00000000..d19103ea
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00027.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00028.png b/tests/functional/snapshots/nanos/test_sign_message_long/00028.png
new file mode 100644
index 00000000..506c2d4d
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00028.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00029.png b/tests/functional/snapshots/nanos/test_sign_message_long/00029.png
new file mode 100644
index 00000000..3582fc0a
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00029.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00030.png b/tests/functional/snapshots/nanos/test_sign_message_long/00030.png
new file mode 100644
index 00000000..577a9b11
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00030.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00031.png b/tests/functional/snapshots/nanos/test_sign_message_long/00031.png
new file mode 100644
index 00000000..fa404cbf
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00031.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00032.png b/tests/functional/snapshots/nanos/test_sign_message_long/00032.png
new file mode 100644
index 00000000..7f305393
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00032.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00033.png b/tests/functional/snapshots/nanos/test_sign_message_long/00033.png
new file mode 100644
index 00000000..257e0ff1
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00033.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00034.png b/tests/functional/snapshots/nanos/test_sign_message_long/00034.png
new file mode 100644
index 00000000..266fca81
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00034.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00035.png b/tests/functional/snapshots/nanos/test_sign_message_long/00035.png
new file mode 100644
index 00000000..fa907f07
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00035.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00036.png b/tests/functional/snapshots/nanos/test_sign_message_long/00036.png
new file mode 100644
index 00000000..35c03271
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00036.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00037.png b/tests/functional/snapshots/nanos/test_sign_message_long/00037.png
new file mode 100644
index 00000000..2e14ae41
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00037.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00038.png b/tests/functional/snapshots/nanos/test_sign_message_long/00038.png
new file mode 100644
index 00000000..0f762bea
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00038.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00039.png b/tests/functional/snapshots/nanos/test_sign_message_long/00039.png
new file mode 100644
index 00000000..c5ef6aaf
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00039.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00040.png b/tests/functional/snapshots/nanos/test_sign_message_long/00040.png
new file mode 100644
index 00000000..57a1b864
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00040.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00041.png b/tests/functional/snapshots/nanos/test_sign_message_long/00041.png
new file mode 100644
index 00000000..17b12a0f
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00041.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00042.png b/tests/functional/snapshots/nanos/test_sign_message_long/00042.png
new file mode 100644
index 00000000..77c86de8
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00042.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00043.png b/tests/functional/snapshots/nanos/test_sign_message_long/00043.png
new file mode 100644
index 00000000..0314feac
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00043.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00044.png b/tests/functional/snapshots/nanos/test_sign_message_long/00044.png
new file mode 100644
index 00000000..cf2dc264
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00044.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00045.png b/tests/functional/snapshots/nanos/test_sign_message_long/00045.png
new file mode 100644
index 00000000..c81484c9
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00045.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00046.png b/tests/functional/snapshots/nanos/test_sign_message_long/00046.png
new file mode 100644
index 00000000..926e232a
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00046.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00047.png b/tests/functional/snapshots/nanos/test_sign_message_long/00047.png
new file mode 100644
index 00000000..7f998d7e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00047.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00048.png b/tests/functional/snapshots/nanos/test_sign_message_long/00048.png
new file mode 100644
index 00000000..1ebede2b
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00048.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00049.png b/tests/functional/snapshots/nanos/test_sign_message_long/00049.png
new file mode 100644
index 00000000..d619e7dc
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00049.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00050.png b/tests/functional/snapshots/nanos/test_sign_message_long/00050.png
new file mode 100644
index 00000000..7bbf0107
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00050.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00051.png b/tests/functional/snapshots/nanos/test_sign_message_long/00051.png
new file mode 100644
index 00000000..641422ed
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00051.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00052.png b/tests/functional/snapshots/nanos/test_sign_message_long/00052.png
new file mode 100644
index 00000000..ce0f2506
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00052.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00053.png b/tests/functional/snapshots/nanos/test_sign_message_long/00053.png
new file mode 100644
index 00000000..8be05f75
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00053.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00054.png b/tests/functional/snapshots/nanos/test_sign_message_long/00054.png
new file mode 100644
index 00000000..9fb37c5d
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00054.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00055.png b/tests/functional/snapshots/nanos/test_sign_message_long/00055.png
new file mode 100644
index 00000000..6be5e617
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00055.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00056.png b/tests/functional/snapshots/nanos/test_sign_message_long/00056.png
new file mode 100644
index 00000000..9edc494e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00056.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00057.png b/tests/functional/snapshots/nanos/test_sign_message_long/00057.png
new file mode 100644
index 00000000..3ea18d33
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00057.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00058.png b/tests/functional/snapshots/nanos/test_sign_message_long/00058.png
new file mode 100644
index 00000000..1dc61fb9
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00058.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00059.png b/tests/functional/snapshots/nanos/test_sign_message_long/00059.png
new file mode 100644
index 00000000..76df5120
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00059.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00060.png b/tests/functional/snapshots/nanos/test_sign_message_long/00060.png
new file mode 100644
index 00000000..3e4992dc
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00060.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00061.png b/tests/functional/snapshots/nanos/test_sign_message_long/00061.png
new file mode 100644
index 00000000..d406f438
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00061.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00062.png b/tests/functional/snapshots/nanos/test_sign_message_long/00062.png
new file mode 100644
index 00000000..09b221dd
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00062.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00063.png b/tests/functional/snapshots/nanos/test_sign_message_long/00063.png
new file mode 100644
index 00000000..be29d5e0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00063.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00064.png b/tests/functional/snapshots/nanos/test_sign_message_long/00064.png
new file mode 100644
index 00000000..738f42ec
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00064.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00065.png b/tests/functional/snapshots/nanos/test_sign_message_long/00065.png
new file mode 100644
index 00000000..7439563f
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00065.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00066.png b/tests/functional/snapshots/nanos/test_sign_message_long/00066.png
new file mode 100644
index 00000000..ea689adf
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00066.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00067.png b/tests/functional/snapshots/nanos/test_sign_message_long/00067.png
new file mode 100644
index 00000000..5950501f
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00067.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00068.png b/tests/functional/snapshots/nanos/test_sign_message_long/00068.png
new file mode 100644
index 00000000..03fecb71
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00068.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00069.png b/tests/functional/snapshots/nanos/test_sign_message_long/00069.png
new file mode 100644
index 00000000..6d5fd169
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00069.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00070.png b/tests/functional/snapshots/nanos/test_sign_message_long/00070.png
new file mode 100644
index 00000000..bdd8cc5e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00070.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00071.png b/tests/functional/snapshots/nanos/test_sign_message_long/00071.png
new file mode 100644
index 00000000..2948a655
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00071.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00072.png b/tests/functional/snapshots/nanos/test_sign_message_long/00072.png
new file mode 100644
index 00000000..a6547499
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00072.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00073.png b/tests/functional/snapshots/nanos/test_sign_message_long/00073.png
new file mode 100644
index 00000000..02697b37
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00073.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00074.png b/tests/functional/snapshots/nanos/test_sign_message_long/00074.png
new file mode 100644
index 00000000..b2a14b6c
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00074.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00075.png b/tests/functional/snapshots/nanos/test_sign_message_long/00075.png
new file mode 100644
index 00000000..d27ae6bb
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00075.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00076.png b/tests/functional/snapshots/nanos/test_sign_message_long/00076.png
new file mode 100644
index 00000000..549d66d8
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00076.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00077.png b/tests/functional/snapshots/nanos/test_sign_message_long/00077.png
new file mode 100644
index 00000000..4b4fd32c
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00077.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00078.png b/tests/functional/snapshots/nanos/test_sign_message_long/00078.png
new file mode 100644
index 00000000..cea20b0d
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00078.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00079.png b/tests/functional/snapshots/nanos/test_sign_message_long/00079.png
new file mode 100644
index 00000000..d06d03f6
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00079.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00080.png b/tests/functional/snapshots/nanos/test_sign_message_long/00080.png
new file mode 100644
index 00000000..449a2e20
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00080.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00081.png b/tests/functional/snapshots/nanos/test_sign_message_long/00081.png
new file mode 100644
index 00000000..c067cdb8
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00081.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00082.png b/tests/functional/snapshots/nanos/test_sign_message_long/00082.png
new file mode 100644
index 00000000..81d1a9cb
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00082.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00083.png b/tests/functional/snapshots/nanos/test_sign_message_long/00083.png
new file mode 100644
index 00000000..97b1053e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00083.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00084.png b/tests/functional/snapshots/nanos/test_sign_message_long/00084.png
new file mode 100644
index 00000000..b99436a1
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00084.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00085.png b/tests/functional/snapshots/nanos/test_sign_message_long/00085.png
new file mode 100644
index 00000000..e464076f
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00085.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00086.png b/tests/functional/snapshots/nanos/test_sign_message_long/00086.png
new file mode 100644
index 00000000..5b67acde
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00086.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00087.png b/tests/functional/snapshots/nanos/test_sign_message_long/00087.png
new file mode 100644
index 00000000..7424d5a2
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00087.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00088.png b/tests/functional/snapshots/nanos/test_sign_message_long/00088.png
new file mode 100644
index 00000000..8e8a5cc1
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00088.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00089.png b/tests/functional/snapshots/nanos/test_sign_message_long/00089.png
new file mode 100644
index 00000000..66c411c2
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00089.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_long/00090.png b/tests/functional/snapshots/nanos/test_sign_message_long/00090.png
new file mode 100644
index 00000000..019b9bb0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_long/00090.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_refused/00000.png b/tests/functional/snapshots/nanos/test_sign_message_refused/00000.png
new file mode 100644
index 00000000..5caa4c03
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_refused/00000.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_refused/00001.png b/tests/functional/snapshots/nanos/test_sign_message_refused/00001.png
new file mode 100644
index 00000000..a005bed5
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_refused/00001.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_refused/00002.png b/tests/functional/snapshots/nanos/test_sign_message_refused/00002.png
new file mode 100644
index 00000000..5cd876e8
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_refused/00002.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_refused/00003.png b/tests/functional/snapshots/nanos/test_sign_message_refused/00003.png
new file mode 100644
index 00000000..412d4234
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_refused/00003.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_refused/00004.png b/tests/functional/snapshots/nanos/test_sign_message_refused/00004.png
new file mode 100644
index 00000000..16caadee
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_refused/00004.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_refused/00005.png b/tests/functional/snapshots/nanos/test_sign_message_refused/00005.png
new file mode 100644
index 00000000..66c411c2
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_refused/00005.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_refused/00006.png b/tests/functional/snapshots/nanos/test_sign_message_refused/00006.png
new file mode 100644
index 00000000..9c7e7049
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_refused/00006.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_refused/00007.png b/tests/functional/snapshots/nanos/test_sign_message_refused/00007.png
new file mode 100644
index 00000000..019b9bb0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_refused/00007.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_short/00000.png b/tests/functional/snapshots/nanos/test_sign_message_short/00000.png
new file mode 100644
index 00000000..5caa4c03
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_short/00000.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_short/00001.png b/tests/functional/snapshots/nanos/test_sign_message_short/00001.png
new file mode 100644
index 00000000..a005bed5
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_short/00001.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_short/00002.png b/tests/functional/snapshots/nanos/test_sign_message_short/00002.png
new file mode 100644
index 00000000..5cd876e8
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_short/00002.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_short/00003.png b/tests/functional/snapshots/nanos/test_sign_message_short/00003.png
new file mode 100644
index 00000000..412d4234
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_short/00003.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_short/00004.png b/tests/functional/snapshots/nanos/test_sign_message_short/00004.png
new file mode 100644
index 00000000..16caadee
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_short/00004.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_short/00005.png b/tests/functional/snapshots/nanos/test_sign_message_short/00005.png
new file mode 100644
index 00000000..66c411c2
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_short/00005.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_message_short/00006.png b/tests/functional/snapshots/nanos/test_sign_message_short/00006.png
new file mode 100644
index 00000000..019b9bb0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_message_short/00006.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_burn/00000.png b/tests/functional/snapshots/nanos/test_sign_transaction_burn/00000.png
new file mode 100644
index 00000000..4356f205
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_burn/00000.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_burn/00001.png b/tests/functional/snapshots/nanos/test_sign_transaction_burn/00001.png
new file mode 100644
index 00000000..2135fb13
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_burn/00001.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_burn/00002.png b/tests/functional/snapshots/nanos/test_sign_transaction_burn/00002.png
new file mode 100644
index 00000000..fbf10c59
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_burn/00002.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_burn/00003.png b/tests/functional/snapshots/nanos/test_sign_transaction_burn/00003.png
new file mode 100644
index 00000000..66c411c2
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_burn/00003.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_burn/00004.png b/tests/functional/snapshots/nanos/test_sign_transaction_burn/00004.png
new file mode 100644
index 00000000..019b9bb0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_burn/00004.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00000.png b/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00000.png
new file mode 100644
index 00000000..7b167faa
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00000.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00001.png b/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00001.png
new file mode 100644
index 00000000..2ef34412
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00001.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00002.png b/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00002.png
new file mode 100644
index 00000000..3b1606f8
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00002.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00003.png b/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00003.png
new file mode 100644
index 00000000..f2c03d23
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00003.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00004.png b/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00004.png
new file mode 100644
index 00000000..74f85282
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00004.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00005.png b/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00005.png
new file mode 100644
index 00000000..66c411c2
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00005.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00006.png b/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00006.png
new file mode 100644
index 00000000..019b9bb0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_ipfs/00006.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00000.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00000.png
new file mode 100644
index 00000000..22c51fdc
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00000.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00001.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00001.png
new file mode 100644
index 00000000..705cfb35
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00001.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00002.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00002.png
new file mode 100644
index 00000000..9e1e987a
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00002.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00003.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00003.png
new file mode 100644
index 00000000..f0e8658b
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00003.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00004.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00004.png
new file mode 100644
index 00000000..c76e8546
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00004.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00005.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00005.png
new file mode 100644
index 00000000..eb69acc3
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00005.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00006.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00006.png
new file mode 100644
index 00000000..cd2eb67b
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00006.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00007.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00007.png
new file mode 100644
index 00000000..c8ec7d0a
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00007.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00008.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00008.png
new file mode 100644
index 00000000..1f6e99c9
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00008.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00009.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00009.png
new file mode 100644
index 00000000..9eae916d
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00009.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00010.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00010.png
new file mode 100644
index 00000000..3b505a58
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00010.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00011.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00011.png
new file mode 100644
index 00000000..179d37ae
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00011.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00012.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00012.png
new file mode 100644
index 00000000..9a0b267a
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00012.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00013.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00013.png
new file mode 100644
index 00000000..a722b001
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00013.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00014.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00014.png
new file mode 100644
index 00000000..87e1856e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00014.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00015.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00015.png
new file mode 100644
index 00000000..fc85ed11
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00015.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00016.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00016.png
new file mode 100644
index 00000000..1b12c2f0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00016.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00017.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00017.png
new file mode 100644
index 00000000..a1a916ac
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00017.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00018.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00018.png
new file mode 100644
index 00000000..ea15b996
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00018.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00019.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00019.png
new file mode 100644
index 00000000..aacafb42
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00019.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00020.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00020.png
new file mode 100644
index 00000000..b2e26ebd
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00020.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00021.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00021.png
new file mode 100644
index 00000000..820822c2
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00021.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00022.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00022.png
new file mode 100644
index 00000000..1ffbdbfc
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00022.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00023.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00023.png
new file mode 100644
index 00000000..d67b574a
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00023.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00024.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00024.png
new file mode 100644
index 00000000..caeac4c8
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00024.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00025.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00025.png
new file mode 100644
index 00000000..3fe5d4ca
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00025.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00026.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00026.png
new file mode 100644
index 00000000..58c2b843
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00026.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00027.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00027.png
new file mode 100644
index 00000000..6122e475
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00027.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00028.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00028.png
new file mode 100644
index 00000000..b9a8577e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00028.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00029.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00029.png
new file mode 100644
index 00000000..9eace8e3
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00029.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00030.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00030.png
new file mode 100644
index 00000000..bcb2284e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00030.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00031.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00031.png
new file mode 100644
index 00000000..df3dd877
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00031.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00032.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00032.png
new file mode 100644
index 00000000..e969f2d1
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00032.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00033.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00033.png
new file mode 100644
index 00000000..323f736b
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00033.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00034.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00034.png
new file mode 100644
index 00000000..27cdb1ec
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00034.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00035.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00035.png
new file mode 100644
index 00000000..ef3d6bad
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00035.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00036.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00036.png
new file mode 100644
index 00000000..884bc5bc
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00036.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00037.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00037.png
new file mode 100644
index 00000000..a7f1d8f1
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00037.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00038.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00038.png
new file mode 100644
index 00000000..d06df4eb
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00038.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00039.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00039.png
new file mode 100644
index 00000000..2301e999
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00039.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00040.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00040.png
new file mode 100644
index 00000000..5893ed20
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00040.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00041.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00041.png
new file mode 100644
index 00000000..4c1f8737
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00041.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00042.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00042.png
new file mode 100644
index 00000000..82facfe0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00042.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00043.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00043.png
new file mode 100644
index 00000000..4834cdef
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00043.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00044.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00044.png
new file mode 100644
index 00000000..596c402c
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00044.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00045.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00045.png
new file mode 100644
index 00000000..278c3281
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00045.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00046.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00046.png
new file mode 100644
index 00000000..a5f96416
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00046.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00047.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00047.png
new file mode 100644
index 00000000..59fb927e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00047.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00048.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00048.png
new file mode 100644
index 00000000..df8ac99d
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00048.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00049.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00049.png
new file mode 100644
index 00000000..10ddd467
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00049.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00050.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00050.png
new file mode 100644
index 00000000..84be9482
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00050.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00051.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00051.png
new file mode 100644
index 00000000..9881e9be
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00051.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00052.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00052.png
new file mode 100644
index 00000000..66c411c2
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00052.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00053.png b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00053.png
new file mode 100644
index 00000000..019b9bb0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_transfer/00053.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_vote/00000.png b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00000.png
new file mode 100644
index 00000000..92258070
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00000.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_vote/00001.png b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00001.png
new file mode 100644
index 00000000..ff2eef9d
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00001.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_vote/00002.png b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00002.png
new file mode 100644
index 00000000..ee9668f4
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00002.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_vote/00003.png b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00003.png
new file mode 100644
index 00000000..5bfb49da
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00003.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_vote/00004.png b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00004.png
new file mode 100644
index 00000000..60fc7f4a
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00004.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_vote/00005.png b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00005.png
new file mode 100644
index 00000000..8d1b6f03
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00005.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_vote/00006.png b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00006.png
new file mode 100644
index 00000000..9b157943
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00006.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_vote/00007.png b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00007.png
new file mode 100644
index 00000000..fbf10c59
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00007.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_vote/00008.png b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00008.png
new file mode 100644
index 00000000..66c411c2
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00008.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_vote/00009.png b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00009.png
new file mode 100644
index 00000000..019b9bb0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_vote/00009.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_vote_cancel/00000.png b/tests/functional/snapshots/nanos/test_sign_transaction_vote_cancel/00000.png
new file mode 100644
index 00000000..23f1351e
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_vote_cancel/00000.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_vote_cancel/00001.png b/tests/functional/snapshots/nanos/test_sign_transaction_vote_cancel/00001.png
new file mode 100644
index 00000000..fbf10c59
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_vote_cancel/00001.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_vote_cancel/00002.png b/tests/functional/snapshots/nanos/test_sign_transaction_vote_cancel/00002.png
new file mode 100644
index 00000000..66c411c2
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_vote_cancel/00002.png differ
diff --git a/tests/functional/snapshots/nanos/test_sign_transaction_vote_cancel/00003.png b/tests/functional/snapshots/nanos/test_sign_transaction_vote_cancel/00003.png
new file mode 100644
index 00000000..019b9bb0
Binary files /dev/null and b/tests/functional/snapshots/nanos/test_sign_transaction_vote_cancel/00003.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_address_confirm_accepted/00000.png b/tests/functional/snapshots/nanosp/test_get_address_confirm_accepted/00000.png
new file mode 100644
index 00000000..19c9a3e1
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_address_confirm_accepted/00000.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_address_confirm_accepted/00001.png b/tests/functional/snapshots/nanosp/test_get_address_confirm_accepted/00001.png
new file mode 100644
index 00000000..2cbafa44
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_address_confirm_accepted/00001.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_address_confirm_accepted/00002.png b/tests/functional/snapshots/nanosp/test_get_address_confirm_accepted/00002.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_address_confirm_accepted/00002.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_address_confirm_accepted/00003.png b/tests/functional/snapshots/nanosp/test_get_address_confirm_accepted/00003.png
new file mode 100644
index 00000000..c80fa832
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_address_confirm_accepted/00003.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_address_confirm_refused/00000.png b/tests/functional/snapshots/nanosp/test_get_address_confirm_refused/00000.png
new file mode 100644
index 00000000..19c9a3e1
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_address_confirm_refused/00000.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_address_confirm_refused/00001.png b/tests/functional/snapshots/nanosp/test_get_address_confirm_refused/00001.png
new file mode 100644
index 00000000..2cbafa44
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_address_confirm_refused/00001.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_address_confirm_refused/00002.png b/tests/functional/snapshots/nanosp/test_get_address_confirm_refused/00002.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_address_confirm_refused/00002.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_address_confirm_refused/00003.png b/tests/functional/snapshots/nanosp/test_get_address_confirm_refused/00003.png
new file mode 100644
index 00000000..c9222461
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_address_confirm_refused/00003.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_address_confirm_refused/00004.png b/tests/functional/snapshots/nanosp/test_get_address_confirm_refused/00004.png
new file mode 100644
index 00000000..c80fa832
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_address_confirm_refused/00004.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_chaincode_confirm_accepted/00000.png b/tests/functional/snapshots/nanosp/test_get_public_key_chaincode_confirm_accepted/00000.png
new file mode 100644
index 00000000..6212c8bf
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_chaincode_confirm_accepted/00000.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_chaincode_confirm_accepted/00001.png b/tests/functional/snapshots/nanosp/test_get_public_key_chaincode_confirm_accepted/00001.png
new file mode 100644
index 00000000..eb20fe5a
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_chaincode_confirm_accepted/00001.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_chaincode_confirm_accepted/00002.png b/tests/functional/snapshots/nanosp/test_get_public_key_chaincode_confirm_accepted/00002.png
new file mode 100644
index 00000000..0e3e2235
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_chaincode_confirm_accepted/00002.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_chaincode_confirm_accepted/00003.png b/tests/functional/snapshots/nanosp/test_get_public_key_chaincode_confirm_accepted/00003.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_chaincode_confirm_accepted/00003.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_chaincode_confirm_accepted/00004.png b/tests/functional/snapshots/nanosp/test_get_public_key_chaincode_confirm_accepted/00004.png
new file mode 100644
index 00000000..c80fa832
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_chaincode_confirm_accepted/00004.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00000.png b/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00000.png
new file mode 100644
index 00000000..6212c8bf
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00000.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00001.png b/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00001.png
new file mode 100644
index 00000000..eb20fe5a
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00001.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00002.png b/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00002.png
new file mode 100644
index 00000000..0e3e2235
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00002.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00003.png b/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00003.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00003.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00004.png b/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00004.png
new file mode 100644
index 00000000..c9222461
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00004.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00005.png b/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00005.png
new file mode 100644
index 00000000..c80fa832
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_confirm_refused/00005.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_no_chaincode_confirm_accepted/00000.png b/tests/functional/snapshots/nanosp/test_get_public_key_no_chaincode_confirm_accepted/00000.png
new file mode 100644
index 00000000..6212c8bf
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_no_chaincode_confirm_accepted/00000.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_no_chaincode_confirm_accepted/00001.png b/tests/functional/snapshots/nanosp/test_get_public_key_no_chaincode_confirm_accepted/00001.png
new file mode 100644
index 00000000..eb20fe5a
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_no_chaincode_confirm_accepted/00001.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_no_chaincode_confirm_accepted/00002.png b/tests/functional/snapshots/nanosp/test_get_public_key_no_chaincode_confirm_accepted/00002.png
new file mode 100644
index 00000000..0e3e2235
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_no_chaincode_confirm_accepted/00002.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_no_chaincode_confirm_accepted/00003.png b/tests/functional/snapshots/nanosp/test_get_public_key_no_chaincode_confirm_accepted/00003.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_no_chaincode_confirm_accepted/00003.png differ
diff --git a/tests/functional/snapshots/nanosp/test_get_public_key_no_chaincode_confirm_accepted/00004.png b/tests/functional/snapshots/nanosp/test_get_public_key_no_chaincode_confirm_accepted/00004.png
new file mode 100644
index 00000000..c80fa832
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_get_public_key_no_chaincode_confirm_accepted/00004.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00000.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00000.png
new file mode 100644
index 00000000..76560b8c
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00000.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00001.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00001.png
new file mode 100644
index 00000000..77ef42c3
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00001.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00002.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00002.png
new file mode 100644
index 00000000..f558fdec
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00002.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00003.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00003.png
new file mode 100644
index 00000000..be34227e
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00003.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00004.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00004.png
new file mode 100644
index 00000000..426fb7d6
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00004.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00005.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00005.png
new file mode 100644
index 00000000..61f2e174
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00005.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00006.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00006.png
new file mode 100644
index 00000000..2394d467
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00006.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00007.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00007.png
new file mode 100644
index 00000000..545960b1
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00007.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00008.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00008.png
new file mode 100644
index 00000000..af4a7eab
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00008.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00009.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00009.png
new file mode 100644
index 00000000..08153684
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00009.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00010.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00010.png
new file mode 100644
index 00000000..745d0810
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00010.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00011.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00011.png
new file mode 100644
index 00000000..91bf38fb
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00011.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00012.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00012.png
new file mode 100644
index 00000000..fd105b25
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00012.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00013.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00013.png
new file mode 100644
index 00000000..d6234010
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00013.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00014.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00014.png
new file mode 100644
index 00000000..34143099
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00014.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00015.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00015.png
new file mode 100644
index 00000000..ef7b6710
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00015.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00016.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00016.png
new file mode 100644
index 00000000..046bed7c
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00016.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00017.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00017.png
new file mode 100644
index 00000000..db7a039a
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00017.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00018.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00018.png
new file mode 100644
index 00000000..180b1204
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00018.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00019.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00019.png
new file mode 100644
index 00000000..4a6e0c2c
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00019.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00020.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00020.png
new file mode 100644
index 00000000..feca784b
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00020.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00021.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00021.png
new file mode 100644
index 00000000..88892774
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00021.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00022.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00022.png
new file mode 100644
index 00000000..4c25eca4
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00022.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00023.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00023.png
new file mode 100644
index 00000000..ae2ca3f2
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00023.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00024.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00024.png
new file mode 100644
index 00000000..91b1ce56
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00024.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00025.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00025.png
new file mode 100644
index 00000000..2b830032
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00025.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00026.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00026.png
new file mode 100644
index 00000000..3182fb04
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00026.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00027.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00027.png
new file mode 100644
index 00000000..bb719d45
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00027.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00028.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00028.png
new file mode 100644
index 00000000..f20a23ce
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00028.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00029.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00029.png
new file mode 100644
index 00000000..0ce7ebe3
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00029.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00030.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00030.png
new file mode 100644
index 00000000..92754796
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00030.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00031.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00031.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00031.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_long/00032.png b/tests/functional/snapshots/nanosp/test_sign_message_long/00032.png
new file mode 100644
index 00000000..c80fa832
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_long/00032.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_refused/00000.png b/tests/functional/snapshots/nanosp/test_sign_message_refused/00000.png
new file mode 100644
index 00000000..76560b8c
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_refused/00000.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_refused/00001.png b/tests/functional/snapshots/nanosp/test_sign_message_refused/00001.png
new file mode 100644
index 00000000..03097feb
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_refused/00001.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_refused/00002.png b/tests/functional/snapshots/nanosp/test_sign_message_refused/00002.png
new file mode 100644
index 00000000..efb80341
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_refused/00002.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_refused/00003.png b/tests/functional/snapshots/nanosp/test_sign_message_refused/00003.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_refused/00003.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_refused/00004.png b/tests/functional/snapshots/nanosp/test_sign_message_refused/00004.png
new file mode 100644
index 00000000..c9222461
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_refused/00004.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_refused/00005.png b/tests/functional/snapshots/nanosp/test_sign_message_refused/00005.png
new file mode 100644
index 00000000..c80fa832
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_refused/00005.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_short/00000.png b/tests/functional/snapshots/nanosp/test_sign_message_short/00000.png
new file mode 100644
index 00000000..76560b8c
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_short/00000.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_short/00001.png b/tests/functional/snapshots/nanosp/test_sign_message_short/00001.png
new file mode 100644
index 00000000..03097feb
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_short/00001.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_short/00002.png b/tests/functional/snapshots/nanosp/test_sign_message_short/00002.png
new file mode 100644
index 00000000..efb80341
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_short/00002.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_short/00003.png b/tests/functional/snapshots/nanosp/test_sign_message_short/00003.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_short/00003.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_message_short/00004.png b/tests/functional/snapshots/nanosp/test_sign_message_short/00004.png
new file mode 100644
index 00000000..c80fa832
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_message_short/00004.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_burn/00000.png b/tests/functional/snapshots/nanosp/test_sign_transaction_burn/00000.png
new file mode 100644
index 00000000..bf069fd2
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_burn/00000.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_burn/00001.png b/tests/functional/snapshots/nanosp/test_sign_transaction_burn/00001.png
new file mode 100644
index 00000000..d9cd2071
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_burn/00001.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_burn/00002.png b/tests/functional/snapshots/nanosp/test_sign_transaction_burn/00002.png
new file mode 100644
index 00000000..fea4e481
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_burn/00002.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_burn/00003.png b/tests/functional/snapshots/nanosp/test_sign_transaction_burn/00003.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_burn/00003.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_burn/00004.png b/tests/functional/snapshots/nanosp/test_sign_transaction_burn/00004.png
new file mode 100644
index 00000000..c80fa832
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_burn/00004.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_ipfs/00000.png b/tests/functional/snapshots/nanosp/test_sign_transaction_ipfs/00000.png
new file mode 100644
index 00000000..3c04302b
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_ipfs/00000.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_ipfs/00001.png b/tests/functional/snapshots/nanosp/test_sign_transaction_ipfs/00001.png
new file mode 100644
index 00000000..c3af4be0
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_ipfs/00001.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_ipfs/00002.png b/tests/functional/snapshots/nanosp/test_sign_transaction_ipfs/00002.png
new file mode 100644
index 00000000..a1364e7f
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_ipfs/00002.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_ipfs/00003.png b/tests/functional/snapshots/nanosp/test_sign_transaction_ipfs/00003.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_ipfs/00003.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_ipfs/00004.png b/tests/functional/snapshots/nanosp/test_sign_transaction_ipfs/00004.png
new file mode 100644
index 00000000..c80fa832
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_ipfs/00004.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00000.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00000.png
new file mode 100644
index 00000000..e5d8a3e9
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00000.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00001.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00001.png
new file mode 100644
index 00000000..23677d36
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00001.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00002.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00002.png
new file mode 100644
index 00000000..48117967
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00002.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00003.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00003.png
new file mode 100644
index 00000000..a5763d6e
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00003.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00004.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00004.png
new file mode 100644
index 00000000..0345aec8
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00004.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00005.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00005.png
new file mode 100644
index 00000000..c279c704
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00005.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00006.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00006.png
new file mode 100644
index 00000000..6f224982
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00006.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00007.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00007.png
new file mode 100644
index 00000000..a23b40b6
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00007.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00008.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00008.png
new file mode 100644
index 00000000..cfac6268
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00008.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00009.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00009.png
new file mode 100644
index 00000000..fdb967ac
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00009.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00010.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00010.png
new file mode 100644
index 00000000..806c37fe
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00010.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00011.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00011.png
new file mode 100644
index 00000000..7c26e109
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00011.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00012.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00012.png
new file mode 100644
index 00000000..7bea010a
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00012.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00013.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00013.png
new file mode 100644
index 00000000..f7ab16ed
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00013.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00014.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00014.png
new file mode 100644
index 00000000..0e69cd9b
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00014.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00015.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00015.png
new file mode 100644
index 00000000..02d894af
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00015.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00016.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00016.png
new file mode 100644
index 00000000..d93355b0
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00016.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00017.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00017.png
new file mode 100644
index 00000000..28d1b845
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00017.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00018.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00018.png
new file mode 100644
index 00000000..31d8c9fe
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00018.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00019.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00019.png
new file mode 100644
index 00000000..48b4c127
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00019.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00020.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00020.png
new file mode 100644
index 00000000..20384394
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00020.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00021.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00021.png
new file mode 100644
index 00000000..e51f03ab
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00021.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00022.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00022.png
new file mode 100644
index 00000000..ce18bb25
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00022.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00023.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00023.png
new file mode 100644
index 00000000..e199c6b9
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00023.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00024.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00024.png
new file mode 100644
index 00000000..2cee104f
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00024.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00025.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00025.png
new file mode 100644
index 00000000..84261e22
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00025.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00026.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00026.png
new file mode 100644
index 00000000..fb49d223
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00026.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00027.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00027.png
new file mode 100644
index 00000000..8bc79a8c
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00027.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00028.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00028.png
new file mode 100644
index 00000000..8a44a06b
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00028.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00029.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00029.png
new file mode 100644
index 00000000..da45253c
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00029.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00030.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00030.png
new file mode 100644
index 00000000..e7b26e42
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00030.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00031.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00031.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00031.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00032.png b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00032.png
new file mode 100644
index 00000000..c80fa832
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_transfer/00032.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00000.png b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00000.png
new file mode 100644
index 00000000..ae7bbe82
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00000.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00001.png b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00001.png
new file mode 100644
index 00000000..abfab404
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00001.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00002.png b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00002.png
new file mode 100644
index 00000000..b3f6946d
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00002.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00003.png b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00003.png
new file mode 100644
index 00000000..90e4d103
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00003.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00004.png b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00004.png
new file mode 100644
index 00000000..a21acddf
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00004.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00005.png b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00005.png
new file mode 100644
index 00000000..df76ba3c
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00005.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00006.png b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00006.png
new file mode 100644
index 00000000..41036987
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00006.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00007.png b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00007.png
new file mode 100644
index 00000000..fea4e481
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00007.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00008.png b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00008.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00008.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00009.png b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00009.png
new file mode 100644
index 00000000..c80fa832
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_vote/00009.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_vote_cancel/00000.png b/tests/functional/snapshots/nanosp/test_sign_transaction_vote_cancel/00000.png
new file mode 100644
index 00000000..fdad622d
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_vote_cancel/00000.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_vote_cancel/00001.png b/tests/functional/snapshots/nanosp/test_sign_transaction_vote_cancel/00001.png
new file mode 100644
index 00000000..fea4e481
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_vote_cancel/00001.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_vote_cancel/00002.png b/tests/functional/snapshots/nanosp/test_sign_transaction_vote_cancel/00002.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_vote_cancel/00002.png differ
diff --git a/tests/functional/snapshots/nanosp/test_sign_transaction_vote_cancel/00003.png b/tests/functional/snapshots/nanosp/test_sign_transaction_vote_cancel/00003.png
new file mode 100644
index 00000000..c80fa832
Binary files /dev/null and b/tests/functional/snapshots/nanosp/test_sign_transaction_vote_cancel/00003.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_address_confirm_accepted/00000.png b/tests/functional/snapshots/nanox/test_get_address_confirm_accepted/00000.png
new file mode 100644
index 00000000..19c9a3e1
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_address_confirm_accepted/00000.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_address_confirm_accepted/00001.png b/tests/functional/snapshots/nanox/test_get_address_confirm_accepted/00001.png
new file mode 100644
index 00000000..0159f2db
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_address_confirm_accepted/00001.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_address_confirm_accepted/00002.png b/tests/functional/snapshots/nanox/test_get_address_confirm_accepted/00002.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_address_confirm_accepted/00002.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_address_confirm_accepted/00003.png b/tests/functional/snapshots/nanox/test_get_address_confirm_accepted/00003.png
new file mode 100644
index 00000000..d3ed6d6a
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_address_confirm_accepted/00003.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_address_confirm_refused/00000.png b/tests/functional/snapshots/nanox/test_get_address_confirm_refused/00000.png
new file mode 100644
index 00000000..19c9a3e1
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_address_confirm_refused/00000.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_address_confirm_refused/00001.png b/tests/functional/snapshots/nanox/test_get_address_confirm_refused/00001.png
new file mode 100644
index 00000000..0159f2db
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_address_confirm_refused/00001.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_address_confirm_refused/00002.png b/tests/functional/snapshots/nanox/test_get_address_confirm_refused/00002.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_address_confirm_refused/00002.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_address_confirm_refused/00003.png b/tests/functional/snapshots/nanox/test_get_address_confirm_refused/00003.png
new file mode 100644
index 00000000..e90cd9db
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_address_confirm_refused/00003.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_address_confirm_refused/00004.png b/tests/functional/snapshots/nanox/test_get_address_confirm_refused/00004.png
new file mode 100644
index 00000000..d3ed6d6a
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_address_confirm_refused/00004.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_chaincode_confirm_accepted/00000.png b/tests/functional/snapshots/nanox/test_get_public_key_chaincode_confirm_accepted/00000.png
new file mode 100644
index 00000000..33eefd2c
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_chaincode_confirm_accepted/00000.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_chaincode_confirm_accepted/00001.png b/tests/functional/snapshots/nanox/test_get_public_key_chaincode_confirm_accepted/00001.png
new file mode 100644
index 00000000..4d5a34c9
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_chaincode_confirm_accepted/00001.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_chaincode_confirm_accepted/00002.png b/tests/functional/snapshots/nanox/test_get_public_key_chaincode_confirm_accepted/00002.png
new file mode 100644
index 00000000..74f2b028
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_chaincode_confirm_accepted/00002.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_chaincode_confirm_accepted/00003.png b/tests/functional/snapshots/nanox/test_get_public_key_chaincode_confirm_accepted/00003.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_chaincode_confirm_accepted/00003.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_chaincode_confirm_accepted/00004.png b/tests/functional/snapshots/nanox/test_get_public_key_chaincode_confirm_accepted/00004.png
new file mode 100644
index 00000000..d3ed6d6a
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_chaincode_confirm_accepted/00004.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00000.png b/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00000.png
new file mode 100644
index 00000000..33eefd2c
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00000.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00001.png b/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00001.png
new file mode 100644
index 00000000..4d5a34c9
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00001.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00002.png b/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00002.png
new file mode 100644
index 00000000..74f2b028
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00002.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00003.png b/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00003.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00003.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00004.png b/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00004.png
new file mode 100644
index 00000000..e90cd9db
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00004.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00005.png b/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00005.png
new file mode 100644
index 00000000..d3ed6d6a
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_confirm_refused/00005.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_no_chaincode_confirm_accepted/00000.png b/tests/functional/snapshots/nanox/test_get_public_key_no_chaincode_confirm_accepted/00000.png
new file mode 100644
index 00000000..33eefd2c
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_no_chaincode_confirm_accepted/00000.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_no_chaincode_confirm_accepted/00001.png b/tests/functional/snapshots/nanox/test_get_public_key_no_chaincode_confirm_accepted/00001.png
new file mode 100644
index 00000000..4d5a34c9
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_no_chaincode_confirm_accepted/00001.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_no_chaincode_confirm_accepted/00002.png b/tests/functional/snapshots/nanox/test_get_public_key_no_chaincode_confirm_accepted/00002.png
new file mode 100644
index 00000000..74f2b028
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_no_chaincode_confirm_accepted/00002.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_no_chaincode_confirm_accepted/00003.png b/tests/functional/snapshots/nanox/test_get_public_key_no_chaincode_confirm_accepted/00003.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_no_chaincode_confirm_accepted/00003.png differ
diff --git a/tests/functional/snapshots/nanox/test_get_public_key_no_chaincode_confirm_accepted/00004.png b/tests/functional/snapshots/nanox/test_get_public_key_no_chaincode_confirm_accepted/00004.png
new file mode 100644
index 00000000..d3ed6d6a
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_get_public_key_no_chaincode_confirm_accepted/00004.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00000.png b/tests/functional/snapshots/nanox/test_sign_message_long/00000.png
new file mode 100644
index 00000000..76560b8c
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00000.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00001.png b/tests/functional/snapshots/nanox/test_sign_message_long/00001.png
new file mode 100644
index 00000000..e978fccb
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00001.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00002.png b/tests/functional/snapshots/nanox/test_sign_message_long/00002.png
new file mode 100644
index 00000000..10d35a1d
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00002.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00003.png b/tests/functional/snapshots/nanox/test_sign_message_long/00003.png
new file mode 100644
index 00000000..5672d628
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00003.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00004.png b/tests/functional/snapshots/nanox/test_sign_message_long/00004.png
new file mode 100644
index 00000000..426fb7d6
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00004.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00005.png b/tests/functional/snapshots/nanox/test_sign_message_long/00005.png
new file mode 100644
index 00000000..44f8167c
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00005.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00006.png b/tests/functional/snapshots/nanox/test_sign_message_long/00006.png
new file mode 100644
index 00000000..2394d467
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00006.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00007.png b/tests/functional/snapshots/nanox/test_sign_message_long/00007.png
new file mode 100644
index 00000000..48cf50b6
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00007.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00008.png b/tests/functional/snapshots/nanox/test_sign_message_long/00008.png
new file mode 100644
index 00000000..4c0a56b1
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00008.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00009.png b/tests/functional/snapshots/nanox/test_sign_message_long/00009.png
new file mode 100644
index 00000000..e3c75c9e
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00009.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00010.png b/tests/functional/snapshots/nanox/test_sign_message_long/00010.png
new file mode 100644
index 00000000..b9ab3991
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00010.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00011.png b/tests/functional/snapshots/nanox/test_sign_message_long/00011.png
new file mode 100644
index 00000000..91bf38fb
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00011.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00012.png b/tests/functional/snapshots/nanox/test_sign_message_long/00012.png
new file mode 100644
index 00000000..c42d5832
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00012.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00013.png b/tests/functional/snapshots/nanox/test_sign_message_long/00013.png
new file mode 100644
index 00000000..9e317478
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00013.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00014.png b/tests/functional/snapshots/nanox/test_sign_message_long/00014.png
new file mode 100644
index 00000000..1b7dd494
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00014.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00015.png b/tests/functional/snapshots/nanox/test_sign_message_long/00015.png
new file mode 100644
index 00000000..8d5eefd5
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00015.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00016.png b/tests/functional/snapshots/nanox/test_sign_message_long/00016.png
new file mode 100644
index 00000000..98f85e5f
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00016.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00017.png b/tests/functional/snapshots/nanox/test_sign_message_long/00017.png
new file mode 100644
index 00000000..b3d5b7ed
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00017.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00018.png b/tests/functional/snapshots/nanox/test_sign_message_long/00018.png
new file mode 100644
index 00000000..d250a2bc
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00018.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00019.png b/tests/functional/snapshots/nanox/test_sign_message_long/00019.png
new file mode 100644
index 00000000..cdac56b2
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00019.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00020.png b/tests/functional/snapshots/nanox/test_sign_message_long/00020.png
new file mode 100644
index 00000000..faf7d6a5
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00020.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00021.png b/tests/functional/snapshots/nanox/test_sign_message_long/00021.png
new file mode 100644
index 00000000..60597107
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00021.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00022.png b/tests/functional/snapshots/nanox/test_sign_message_long/00022.png
new file mode 100644
index 00000000..02ca3a78
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00022.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00023.png b/tests/functional/snapshots/nanox/test_sign_message_long/00023.png
new file mode 100644
index 00000000..0b7204bd
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00023.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00024.png b/tests/functional/snapshots/nanox/test_sign_message_long/00024.png
new file mode 100644
index 00000000..3b43a411
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00024.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00025.png b/tests/functional/snapshots/nanox/test_sign_message_long/00025.png
new file mode 100644
index 00000000..2b830032
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00025.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00026.png b/tests/functional/snapshots/nanox/test_sign_message_long/00026.png
new file mode 100644
index 00000000..e4214f62
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00026.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00027.png b/tests/functional/snapshots/nanox/test_sign_message_long/00027.png
new file mode 100644
index 00000000..bb719d45
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00027.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00028.png b/tests/functional/snapshots/nanox/test_sign_message_long/00028.png
new file mode 100644
index 00000000..3b1448e8
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00028.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00029.png b/tests/functional/snapshots/nanox/test_sign_message_long/00029.png
new file mode 100644
index 00000000..352979f6
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00029.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00030.png b/tests/functional/snapshots/nanox/test_sign_message_long/00030.png
new file mode 100644
index 00000000..92754796
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00030.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00031.png b/tests/functional/snapshots/nanox/test_sign_message_long/00031.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00031.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_long/00032.png b/tests/functional/snapshots/nanox/test_sign_message_long/00032.png
new file mode 100644
index 00000000..d3ed6d6a
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_long/00032.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_refused/00000.png b/tests/functional/snapshots/nanox/test_sign_message_refused/00000.png
new file mode 100644
index 00000000..76560b8c
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_refused/00000.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_refused/00001.png b/tests/functional/snapshots/nanox/test_sign_message_refused/00001.png
new file mode 100644
index 00000000..00cba442
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_refused/00001.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_refused/00002.png b/tests/functional/snapshots/nanox/test_sign_message_refused/00002.png
new file mode 100644
index 00000000..efb80341
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_refused/00002.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_refused/00003.png b/tests/functional/snapshots/nanox/test_sign_message_refused/00003.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_refused/00003.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_refused/00004.png b/tests/functional/snapshots/nanox/test_sign_message_refused/00004.png
new file mode 100644
index 00000000..e90cd9db
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_refused/00004.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_refused/00005.png b/tests/functional/snapshots/nanox/test_sign_message_refused/00005.png
new file mode 100644
index 00000000..d3ed6d6a
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_refused/00005.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_short/00000.png b/tests/functional/snapshots/nanox/test_sign_message_short/00000.png
new file mode 100644
index 00000000..76560b8c
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_short/00000.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_short/00001.png b/tests/functional/snapshots/nanox/test_sign_message_short/00001.png
new file mode 100644
index 00000000..00cba442
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_short/00001.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_short/00002.png b/tests/functional/snapshots/nanox/test_sign_message_short/00002.png
new file mode 100644
index 00000000..efb80341
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_short/00002.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_short/00003.png b/tests/functional/snapshots/nanox/test_sign_message_short/00003.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_short/00003.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_message_short/00004.png b/tests/functional/snapshots/nanox/test_sign_message_short/00004.png
new file mode 100644
index 00000000..d3ed6d6a
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_message_short/00004.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_burn/00000.png b/tests/functional/snapshots/nanox/test_sign_transaction_burn/00000.png
new file mode 100644
index 00000000..bf069fd2
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_burn/00000.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_burn/00001.png b/tests/functional/snapshots/nanox/test_sign_transaction_burn/00001.png
new file mode 100644
index 00000000..b4114dad
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_burn/00001.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_burn/00002.png b/tests/functional/snapshots/nanox/test_sign_transaction_burn/00002.png
new file mode 100644
index 00000000..613a80b3
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_burn/00002.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_burn/00003.png b/tests/functional/snapshots/nanox/test_sign_transaction_burn/00003.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_burn/00003.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_burn/00004.png b/tests/functional/snapshots/nanox/test_sign_transaction_burn/00004.png
new file mode 100644
index 00000000..d3ed6d6a
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_burn/00004.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_ipfs/00000.png b/tests/functional/snapshots/nanox/test_sign_transaction_ipfs/00000.png
new file mode 100644
index 00000000..3c04302b
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_ipfs/00000.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_ipfs/00001.png b/tests/functional/snapshots/nanox/test_sign_transaction_ipfs/00001.png
new file mode 100644
index 00000000..5293d788
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_ipfs/00001.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_ipfs/00002.png b/tests/functional/snapshots/nanox/test_sign_transaction_ipfs/00002.png
new file mode 100644
index 00000000..1207c4fc
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_ipfs/00002.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_ipfs/00003.png b/tests/functional/snapshots/nanox/test_sign_transaction_ipfs/00003.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_ipfs/00003.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_ipfs/00004.png b/tests/functional/snapshots/nanox/test_sign_transaction_ipfs/00004.png
new file mode 100644
index 00000000..d3ed6d6a
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_ipfs/00004.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00000.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00000.png
new file mode 100644
index 00000000..e5d8a3e9
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00000.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00001.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00001.png
new file mode 100644
index 00000000..3dd28ca0
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00001.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00002.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00002.png
new file mode 100644
index 00000000..14075ce4
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00002.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00003.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00003.png
new file mode 100644
index 00000000..13636723
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00003.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00004.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00004.png
new file mode 100644
index 00000000..e8bad56b
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00004.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00005.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00005.png
new file mode 100644
index 00000000..83babb94
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00005.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00006.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00006.png
new file mode 100644
index 00000000..0115df09
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00006.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00007.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00007.png
new file mode 100644
index 00000000..a5f7165a
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00007.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00008.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00008.png
new file mode 100644
index 00000000..f4737fb0
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00008.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00009.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00009.png
new file mode 100644
index 00000000..fb73722c
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00009.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00010.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00010.png
new file mode 100644
index 00000000..a4d615a4
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00010.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00011.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00011.png
new file mode 100644
index 00000000..f490d9c9
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00011.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00012.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00012.png
new file mode 100644
index 00000000..b301b7d1
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00012.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00013.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00013.png
new file mode 100644
index 00000000..8e937c65
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00013.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00014.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00014.png
new file mode 100644
index 00000000..ac259102
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00014.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00015.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00015.png
new file mode 100644
index 00000000..378043f8
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00015.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00016.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00016.png
new file mode 100644
index 00000000..ae5a99a6
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00016.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00017.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00017.png
new file mode 100644
index 00000000..77e77835
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00017.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00018.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00018.png
new file mode 100644
index 00000000..83bdff68
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00018.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00019.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00019.png
new file mode 100644
index 00000000..bb791db6
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00019.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00020.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00020.png
new file mode 100644
index 00000000..197b58b3
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00020.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00021.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00021.png
new file mode 100644
index 00000000..92fd3361
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00021.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00022.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00022.png
new file mode 100644
index 00000000..50cc2931
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00022.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00023.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00023.png
new file mode 100644
index 00000000..a8c5c98c
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00023.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00024.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00024.png
new file mode 100644
index 00000000..8516a021
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00024.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00025.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00025.png
new file mode 100644
index 00000000..a84ffa45
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00025.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00026.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00026.png
new file mode 100644
index 00000000..1450c34d
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00026.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00027.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00027.png
new file mode 100644
index 00000000..57a08b46
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00027.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00028.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00028.png
new file mode 100644
index 00000000..2335b431
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00028.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00029.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00029.png
new file mode 100644
index 00000000..698193bb
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00029.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00030.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00030.png
new file mode 100644
index 00000000..32947b3b
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00030.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00031.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00031.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00031.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00032.png b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00032.png
new file mode 100644
index 00000000..d3ed6d6a
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_transfer/00032.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_vote/00000.png b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00000.png
new file mode 100644
index 00000000..ae7bbe82
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00000.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_vote/00001.png b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00001.png
new file mode 100644
index 00000000..abfab404
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00001.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_vote/00002.png b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00002.png
new file mode 100644
index 00000000..f25c827f
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00002.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_vote/00003.png b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00003.png
new file mode 100644
index 00000000..90e4d103
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00003.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_vote/00004.png b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00004.png
new file mode 100644
index 00000000..89a9571b
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00004.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_vote/00005.png b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00005.png
new file mode 100644
index 00000000..df76ba3c
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00005.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_vote/00006.png b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00006.png
new file mode 100644
index 00000000..3dfe3368
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00006.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_vote/00007.png b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00007.png
new file mode 100644
index 00000000..613a80b3
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00007.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_vote/00008.png b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00008.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00008.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_vote/00009.png b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00009.png
new file mode 100644
index 00000000..d3ed6d6a
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_vote/00009.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_vote_cancel/00000.png b/tests/functional/snapshots/nanox/test_sign_transaction_vote_cancel/00000.png
new file mode 100644
index 00000000..fdad622d
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_vote_cancel/00000.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_vote_cancel/00001.png b/tests/functional/snapshots/nanox/test_sign_transaction_vote_cancel/00001.png
new file mode 100644
index 00000000..613a80b3
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_vote_cancel/00001.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_vote_cancel/00002.png b/tests/functional/snapshots/nanox/test_sign_transaction_vote_cancel/00002.png
new file mode 100644
index 00000000..53ae6519
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_vote_cancel/00002.png differ
diff --git a/tests/functional/snapshots/nanox/test_sign_transaction_vote_cancel/00003.png b/tests/functional/snapshots/nanox/test_sign_transaction_vote_cancel/00003.png
new file mode 100644
index 00000000..d3ed6d6a
Binary files /dev/null and b/tests/functional/snapshots/nanox/test_sign_transaction_vote_cancel/00003.png differ
diff --git a/tests/functional/test_address_cmd.py b/tests/functional/test_address_cmd.py
index a73ee685..3f8647f7 100644
--- a/tests/functional/test_address_cmd.py
+++ b/tests/functional/test_address_cmd.py
@@ -1,50 +1,125 @@
import pytest
-from client.exception import *
-from speculos.client import ApduException
-from client.cmd_builder import InsType
+from ragger.error import ExceptionRAPDU
+from ragger.navigator import NavInsID, NavIns
+from utils import ROOT_SCREENSHOT_PATH
+from application_client.solar_command_sender import (
+ CLA,
+ InsType,
+ SolarCommandSender,
+ Errors,
+)
+from application_client.solar_response_unpacker import unpack_get_address_response
+from constants import (
+ NETWORK_MAINNET,
+ NETWORK_TESTNET,
+ NETWORKS,
+ PATH_MAINNET,
+ PATH_TESTNET,
+)
-def test_get_address(cmd):
- # No Display, Solar Mainnet
- address = cmd.get_address(bip32_path="44'/3333'/0'/0/0", display=0, network=0x3F)
+# In this test we check that the GET_ADDRESS works in non-confirmation mode
+def test_get_address_no_confirm(backend):
+ client = SolarCommandSender(backend)
- assert len(address) == 34
+ for network in NETWORKS:
+ response = client.get_address(
+ path=PATH_TESTNET if network is NETWORK_TESTNET else PATH_MAINNET,
+ network=network,
+ ).data
+
+ address_len, address = unpack_get_address_response(response)
+
+ assert address_len == 34
+ assert address[0] == (ord("D") if network is NETWORK_TESTNET else ord("S"))
+
+
+# In this test we check that the GET_ADDRESS throws on unsupported networks
+def test_get_address_unsupported_network(backend):
+ client = SolarCommandSender(backend)
+ no_confirm = 0x00
+ unsupported_network = 0x3E
+
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(
+ cla=CLA, ins=InsType.GET_ADDRESS, p1=no_confirm, p2=unsupported_network
+ )
+ assert e.value.status == Errors.SW_WRONG_P1P2
+
+
+# In this test we check that the GET_ADDRESS works in confirmation mode
+def test_get_address_confirm_accepted(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ with client.get_address_with_confirmation(
+ path=PATH_MAINNET, network=NETWORK_MAINNET
+ ):
+ # if firmware.device.startswith("nano"):
+ navigator.navigate_until_text_and_compare(
+ NavInsID.RIGHT_CLICK,
+ [NavInsID.BOTH_CLICK],
+ "Approve",
+ ROOT_SCREENSHOT_PATH,
+ test_name,
+ )
+ # else:
+ # instructions = [
+ # NavInsID.USE_CASE_REVIEW_TAP,
+ # NavIns(NavInsID.TOUCH, (200, 335)),
+ # NavInsID.USE_CASE_ADDRESS_CONFIRMATION_EXIT_QR,
+ # NavInsID.USE_CASE_ADDRESS_CONFIRMATION_TAP,
+ # NavInsID.USE_CASE_ADDRESS_CONFIRMATION_CONFIRM,
+ # NavInsID.USE_CASE_STATUS_DISMISS
+ # ]
+ # navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH,
+ # test_name,
+ # instructions)
+ response = client.get_async_response().data
+ address_len, address = unpack_get_address_response(response)
+
+ assert address_len == 34
assert address[0] == ord("S")
- # No Display, Solar Testnet
- address2 = cmd.get_address(bip32_path="44'/1'/0'/0/0", display=0, network=0x1E)
-
- assert len(address2) == 34
- assert address2[0] == ord("D")
-
- # Display, Solar Mainnet
- address3 = cmd.get_address(
- bip32_path="44'/3333'/0'/0/0",
- display=1,
- network=0x3F,
- n_screens=4,
- )
-
- assert len(address3) == 34
- assert address3[0] == ord("S")
-
- # Display, Solar Testnet
- address4 = cmd.get_address(
- bip32_path="44'/1'/0'/0/0",
- display=1,
- network=0x1E,
- n_screens=4,
- )
-
- assert len(address4) == 34
- assert address4[0] == ord("D")
-
-
-@pytest.mark.xfail(raises=WrongP1P2Error, strict=True)
-def test_wrong_network(cmd):
- try:
- cmd.get_address(bip32_path="44'/3333'/0'/0/0", display=0, network=0x3E)
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_GET_ADDRESS)
+
+# In this test we check that the GET_ADDRESS in confirmation mode replies an error if the user refuses
+def test_get_address_confirm_refused(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ # if firmware.device.startswith("nano"):
+ with pytest.raises(ExceptionRAPDU) as e:
+ with client.get_address_with_confirmation(
+ path=PATH_MAINNET, network=NETWORK_MAINNET
+ ):
+ navigator.navigate_until_text_and_compare(
+ NavInsID.RIGHT_CLICK,
+ [NavInsID.BOTH_CLICK],
+ "Reject",
+ ROOT_SCREENSHOT_PATH,
+ test_name,
+ )
+ # Assert that we have received a refusal
+ assert e.value.status == Errors.SW_DENY
+ assert len(e.value.data) == 0
+ # else: # stax
+ # instructions_set = [
+ # [
+ # NavInsID.USE_CASE_REVIEW_REJECT,
+ # NavInsID.USE_CASE_STATUS_DISMISS
+ # ],
+ # [
+ # NavInsID.USE_CASE_REVIEW_TAP,
+ # NavInsID.USE_CASE_ADDRESS_CONFIRMATION_CANCEL,
+ # NavInsID.USE_CASE_STATUS_DISMISS
+ # ]
+ # ]
+ # for i, instructions in enumerate(instructions_set):
+ # with pytest.raises(ExceptionRAPDU) as e:
+ # with client.get_public_key_with_confirmation(path=path):
+ # navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH,
+ # test_name + f"/part{i}",
+ # instructions)
+ # # Assert that we have received a refusal
+ # assert e.value.status == Errors.SW_DENY
+ # assert len(e.value.data) == 0
diff --git a/tests/functional/test_appname_cmd.py b/tests/functional/test_appname_cmd.py
index 871df1c2..929fff28 100644
--- a/tests/functional/test_appname_cmd.py
+++ b/tests/functional/test_appname_cmd.py
@@ -1,2 +1,12 @@
-def test_app_name(cmd):
- assert cmd.get_app_name() == "Solar"
+from application_client.solar_command_sender import SolarCommandSender
+from application_client.solar_response_unpacker import unpack_get_app_name_response
+
+
+# In this test we check that the GET_APP_NAME replies the application name
+def test_app_name(backend):
+ # Use the app interface instead of raw interface
+ client = SolarCommandSender(backend)
+ # Send the GET_APP_NAME instruction to the app
+ response = client.get_app_name()
+ # Assert that we have received the correct appname
+ assert unpack_get_app_name_response(response.data) == "Solar"
diff --git a/tests/functional/test_error_cmd.py b/tests/functional/test_error_cmd.py
index 194c9945..1e25a52e 100644
--- a/tests/functional/test_error_cmd.py
+++ b/tests/functional/test_error_cmd.py
@@ -1,140 +1,67 @@
import pytest
-from client.exception import *
-from speculos.client import ApduException
+from ragger.error import ExceptionRAPDU
+from application_client.solar_command_sender import CLA, InsType, P1, P2, Errors
-@pytest.mark.xfail(raises=ClaNotSupportedError, strict=True)
-def test_bad_cla(cmd):
- try:
- cmd.transport.apdu_exchange(
- cla=0xA0, ins=0xB2, p1=0x00, p2=0x00, cdata=b"" # 0xa0 instead of 0xe0
- )
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=0xB2)
+# Ensure the app returns an error when a bad CLA is used
+def test_bad_cla(backend):
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(cla=CLA + 1, ins=InsType.GET_VERSION)
+ assert e.value.status == Errors.SW_CLA_NOT_SUPPORTED
-@pytest.mark.xfail(raises=InsNotSupportedError, strict=True)
-def test_bad_ins(cmd):
- try:
- cmd.transport.apdu_exchange(
- cla=0xE0, ins=0xFF, p1=0x00, p2=0x00, cdata=b"" # bad INS
- )
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=0xFF)
+# Ensure the app returns an error when a bad INS is used
+def test_bad_ins(backend):
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(cla=CLA, ins=0xFF)
+ assert e.value.status == Errors.SW_INS_NOT_SUPPORTED
-@pytest.mark.xfail(raises=WrongP1P2Error, strict=True)
-def test_wrong_p1p2(cmd):
- try:
- cmd.transport.apdu_exchange(
- cla=0xE0, ins=0xA1, p1=0x01, p2=0x00, cdata=b"" # 0x01 instead of 0x00
+# Ensure the app returns an error when a bad P1 or P2 is used
+def test_wrong_p1p2(backend):
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(
+ cla=CLA, ins=InsType.GET_VERSION, p1=P1.P1_START + 1, p2=P2.P2_LAST
)
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=0xA1)
-
-
-@pytest.mark.xfail(raises=WrongDataLengthError, strict=True)
-def test_wrong_data_length(cmd):
- try:
- # APDUs must be at least 5 bytes: CLA, INS, P1, P2, Lc.
- cmd.transport.apdu_exchange_raw("E000")
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=None)
-
-
-@pytest.mark.xfail(raises=OutOfOrderReqError, strict=True)
-def test_wrong_order(cmd):
- try:
- cmd.transport.apdu_exchange(
- cla=0xE0,
- ins=0xC1,
- p1=0x00,
- p2=0x80,
- cdata=bytes.fromhex("058000002c80000d05800000000000000000000000"),
+ assert e.value.status == Errors.SW_WRONG_P1P2
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(
+ cla=CLA, ins=InsType.GET_VERSION, p1=P1.P1_START, p2=P2.P2_MORE
)
-
- cmd.transport.apdu_exchange(
- cla=0xE0, ins=0xC1, p1=0x01, p2=0x80, cdata=b"a" * 255
+ assert e.value.status == Errors.SW_WRONG_P1P2
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(
+ cla=CLA, ins=InsType.GET_APP_NAME, p1=P1.P1_START + 1, p2=P2.P2_LAST
)
-
- cmd.transport.apdu_exchange(
- cla=0xE0, ins=0xC1, p1=0x03, p2=0x00, cdata=b"a" # wrong p1
- )
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=0xC1)
-
-
-@pytest.mark.xfail(raises=WrongTxLengthError, strict=True)
-def test_not_full_req(cmd):
- try:
- cmd.transport.apdu_exchange(
- cla=0xE0,
- ins=0xC1,
- p1=0x00,
- p2=0x80,
- cdata=bytes.fromhex("058000002c80000d05800000000000000000000000"),
- )
-
- cmd.transport.apdu_exchange(
- cla=0xE0, ins=0xC1, p1=0x01, p2=0x80, cdata=b"a" * 255
- )
-
- cmd.transport.apdu_exchange(
- cla=0xE0,
- ins=0xC1,
- p1=0x02,
- p2=0x80,
- cdata=b"a" * 254, # more but chunk not full
- )
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=0xC1)
-
-
-@pytest.mark.xfail(raises=BadStateError, strict=True)
-def test_instruction_swap(cmd):
- try:
- cmd.transport.apdu_exchange(
- cla=0xE0,
- ins=0xC1,
- p1=0x00,
- p2=0x80,
- cdata=bytes.fromhex("058000002c80000d05800000000000000000000000"),
- )
-
- cmd.transport.apdu_exchange(
- cla=0xE0, ins=0xC1, p1=0x01, p2=0x80, cdata=b"a" * 255
- )
-
- cmd.transport.apdu_exchange(
- cla=0xE0, ins=0xC2, p1=0x02, p2=0x80, cdata=b"b" * 255
- )
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=0xC2)
-
-
-@pytest.mark.xfail(raises=BadStateError, strict=True)
-def test_state_cleared(cmd):
- try:
- cmd.transport.apdu_exchange(
- cla=0xE0,
- ins=0xC1,
- p1=0x00,
- p2=0x80,
- cdata=bytes.fromhex("058000002c80000d05800000000000000000000000"),
- )
-
- cmd.transport.apdu_exchange_with_buttons(
- cla=0xE0,
- ins=0xC1,
- p1=0x01,
- p2=0x00,
- cdata=bytes.fromhex("fd00" + "63" * 253),
- n_screens=13,
- )
-
- cmd.transport.apdu_exchange(
- cla=0xE0, ins=0xC1, p1=0x02, p2=0x00, cdata=b"b" * 255
+ assert e.value.status == Errors.SW_WRONG_P1P2
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(
+ cla=CLA, ins=InsType.GET_APP_NAME, p1=P1.P1_START, p2=P2.P2_MORE
)
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=0xC1)
+ assert e.value.status == Errors.SW_WRONG_P1P2
+
+
+# Ensure the app returns an error when a bad data length is used
+def test_wrong_data_length(backend):
+ # APDUs must be at least 5 bytes: CLA, INS, P1, P2, Lc.
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange_raw(b"E0030000")
+ assert e.value.status == Errors.SW_WRONG_DATA_LENGTH
+ # APDUs advertises a too long length
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange_raw(b"E003000005")
+ assert e.value.status == Errors.SW_WRONG_DATA_LENGTH
+
+
+# Ensure there is no state confusion when trying wrong APDU sequences
+def test_invalid_state(backend):
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START + 1, # Try to continue a flow instead of start a new one
+ p2=P2.P2_MORE,
+ data=b"abcde",
+ ) # data is not parsed in this case
+ assert e.value.status == Errors.SW_BAD_STATE
diff --git a/tests/functional/test_message_sign_cmd.py b/tests/functional/test_message_sign_cmd.py
deleted file mode 100644
index f9fec92d..00000000
--- a/tests/functional/test_message_sign_cmd.py
+++ /dev/null
@@ -1,136 +0,0 @@
-from btclib.ecc import ssa
-import pytest
-from client.exception import *
-from speculos.client import ApduException
-from client.cmd_builder import InsType
-
-
-message1="We are the music makers,\n the dreamers of dreams...\n"
-
-message2="[T]he phrase \"debugging a computer\" was coined in 1947 when Harvard researchers found a moth crushed between the jaws of a relay switch in a Mark II Aiken Relay Calculator. The dead moth was taped to the machine's logbook, which now resides at the National Museum of American History of the Smithsonian Institution.\r\nWhenever the machine broke down, which was often, operators would quip that they were \"debugging\" it.\r\n"
-
-message3="The size and age of the Cosmos are beyond ordinary human understanding. Lost somewhere between immensity and eternity is our tiny planetary home. In a cosmic perspective, most human concerns seem insignificant, even petty. And yet our species is young and curious and brave and shows much promise. In the last few millennia we have made the most astonishing and unexpected discoveries about the Cosmos and our place within it, explorations that are exhilarating to consider. They remind us that humans have evolved to wonder, that understanding is a joy, that knowledge is prerequisite to survival. I believe our future depends on how well we know this Cosmos in which we float like a mote of dust in the morning sky."
-
-message4="A man is flying in a hot air balloon and realizes he is lost. He reduces height and spots a man down below. He lowers the balloon further and shouts: \"Excuse me, can you tell me where I am?\"\nThe man below says: \"Yes you're in a hot air balloon, hovering 30 feet above this field.\"\n\"You must be a software developer,\" says the balloonist.\n\"I am,\" replies the man. \"How did you know?\"\n\"Well,\" says the balloonist, \"everything you have told me is technically correct, but it's of no use to anyone.\"\nThe man below says, \"You must work in business as a manager.\"\n\"I do,\" replies the balloonist, \"but how did you know?\"\n\"Well,\" says the man, \"you don't know where you are or where you are going, but you expect me to be able to help. You're in the same position you were before we met but now it's my fault.\""
-
-message5="\"Okay. About twenty years ago A.T.&T. made a multi-billion-dollar decision to operate its entire long-distance switching system on twelve electronically generated combinations of twelve master tones. Those are the tones you sometimes hear in the background after you've dialed a long-distance number. They decided to use some very simple tones -- the tone for each number is just two fixed single-frequency tones played simultaneously to create a certain beat frequency. Like 1300 cycles per second and 900 cycles per second played together give you the tone for digit 5. Now, what some of these phone phreaks have done is get themselves access to an electric organ. Any cheap family home-entertainment organ. Since the frequencies are public knowledge now -- one blind phone phreak has even had them recorded in one of the talking books for the blind -- they just have to find the musical notes on the organ which correspond to the phone tones. Then they tape them. For instance, to get Ma Bell's tone for the number 1, you press down organ keys F~5 and A~5 (900 and 700 cycles per second) at the same time. To produce the tone for 2 it's F~5 and C~6 (1100 and 700 c.p.s). The phone phreaks circulate the whole list of notes so there's no trial and error anymore.\""
-
-message6="Man is the Reasoning Animal. Such is the claim. I think it is open to dispute. Indeed, my experiments have proven to me that he is the Unreasoning Animal... In truth, man is incurably foolish. Simple things which other animals easily learn, he is incapable of learning. Among my experiments was this. In an hour I taught a cat and a dog to be friends. I put them in a cage. In another hour I taught them to be friends with a rabbit. In the course of two days I was able to add a fox, a goose, a squirrel and some doves. Finally a monkey. They lived together in peace; even affectionately.\n Next, in another cage I confined an Irish Catholic from Tipperary, and as soon as he seemed tame I added a Scotch Presbyterian from Aberdeen. Next a Turk from Constantinople; a Greek Christian from Crete; an Armenian; a Methodist from the wilds of Arkansas; a Buddhist from China; a Brahman from Benares. Finally, a Salvation Army Colonel from Wapping. Then I stayed away for two whole days. When I came back to note results, the cage of Higher Animals was all right, but in the other there was but a chaos of gory odds and ends of turbans and fezzes and plaids and bones and flesh--not a specimen left alive. These Reasoning Animals had disagreed on a theological detail and carried the matter to a Higher Court."
-
-message7="A long, long time ago the World was in an age of Chaos. In the midst of the chaos, in a little kingdom in the land of Hyrule, a legend was being handed down from generation to generation, the legend of the 'Triforce': golden triangles possessing mystical powers. One day, an evil army led by Ganon, the powerful Prince of Darkness, attacked and stole the Triforce of Power. Fearing his wicked rule, princess Zelda split the Triforce of Wisdom into eight fragments and hid them throughout the realm. She commanded her most trustworthy nursemaid, Impa, to escape and search for someone courageous enough to destroy the evil Ganon. Upon hearing this, Ganon grew angry, imprisoned the princess, and sent out a party in search of Impa. Braving forests and mountains, Impa fled for her life from her pursuers. As she reached the very limit of her energy she found herself surrounded by Ganon's evil henchmen. Cornered! What could she do? But wait! All was not lost. A young lad appeared, driving off Ganon's henchmen and saving Impa from a fate worse than death. His name was Link. Impa told Link the story of Zelda and the evil Ganon. Burning with a sense of justice, Link resolved to save Zelda. But Ganon was a powerful opponent. He held the Triforce of Power. Link had to bring the scattered eight fragments of the Triforce of Wisdom together to rebuild the mystical triangle or there would be no chance he could fight his way into Death Mountain where Ganon lived. Can Link really destroy Ganon and save princess Zelda? Only your skill can answer that question. Good luck. Use the Triforce wisely."
-
-
-@pytest.fixture(autouse=True)
-def context(cmd):
- bip32_path: str = "44'/3333'/0'/0/0"
-
- pub_key, chain_code = cmd.get_public_key(
- bip32_path=bip32_path, display=0, chaincode=0
- )
-
- context = {"pkey": pub_key, "chain_code": chain_code, "bip32": bip32_path}
- yield context
-
-
-def test_sign_message(cmd, context):
-
- schnorr_sig = cmd.sign_message(
- bip32_path=context["bip32"], message=message1, n_screens=5
- )
- assert (
- ssa.verify(message1.encode("ascii"), context["pkey"][1:], schnorr_sig) is True
- )
-
- schnorr_sig = cmd.sign_message(
- bip32_path=context["bip32"], message=message2, n_screens=26
- )
- assert (
- ssa.verify(message2.encode("ascii"), context["pkey"][1:], schnorr_sig) is True
- )
-
- schnorr_sig = cmd.sign_message(
- bip32_path=context["bip32"], message=message3, n_screens=43
- )
- assert (
- ssa.verify(message3.encode("ascii"), context["pkey"][1:], schnorr_sig) is True
- )
-
- schnorr_sig = cmd.sign_message(
- bip32_path=context["bip32"], message=message4, n_screens=45
- )
- assert (
- ssa.verify(message4.encode("ascii"), context["pkey"][1:], schnorr_sig) is True
- )
-
- schnorr_sig = cmd.sign_message(
- bip32_path=context["bip32"], message=message5, n_screens=69
- )
- assert (
- ssa.verify(message5.encode("ascii"), context["pkey"][1:], schnorr_sig) is True
- )
-
- schnorr_sig = cmd.sign_message(
- bip32_path=context["bip32"], message=message6, n_screens=70
- )
- assert (
- ssa.verify(message6.encode("ascii"), context["pkey"][1:], schnorr_sig) is True
- )
-
- schnorr_sig = cmd.sign_message(
- bip32_path=context["bip32"], message=message7, n_screens=89
- )
- assert (
- ssa.verify(message7.encode("ascii"), context["pkey"][1:], schnorr_sig) is True
- )
-
-
-@pytest.mark.xfail(raises=TxParsingFailError, strict=True)
-def test_too_long_message(cmd, context):
- try:
- message = "a" * 1598
-
- cmd.sign_message(bip32_path=context["bip32"], message=message)
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_MESSAGE)
-
-
-@pytest.mark.xfail(raises=TxParsingFailError, strict=True)
-def test_not_ascii(cmd, context):
- try:
- message = "\0this should not work"
-
- cmd.sign_message(bip32_path=context["bip32"], message=message)
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_MESSAGE)
-
-
-@pytest.mark.xfail(raises=TxParsingFailError, strict=True)
-def test_not_ascii2(cmd, context):
- try:
- message = "this should not work\r"
-
- cmd.sign_message(bip32_path=context["bip32"], message=message)
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_MESSAGE)
-
-
-@pytest.mark.xfail(raises=TxParsingFailError, strict=True)
-def test_length_validation(cmd):
- try:
- cmd.transport.apdu_exchange(
- cla=0xE0,
- ins=0xC1,
- p1=0x00,
- p2=0x80,
- cdata=bytes.fromhex("058000002c80000d05800000000000000000000000"),
- )
-
- cmd.transport.apdu_exchange(
- cla=0xE0,
- ins=0xC1,
- p1=0x01,
- p2=0x00,
- cdata=bytes.fromhex("fe00" + "63" * 253),
- )
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_MESSAGE)
diff --git a/tests/functional/test_name_version.py b/tests/functional/test_name_version.py
index 98247395..ba15b497 100644
--- a/tests/functional/test_name_version.py
+++ b/tests/functional/test_name_version.py
@@ -1,7 +1,17 @@
-def test_get_app_and_version(cmd, hid):
- if hid:
- # for now it doesn't work with Speculos
- app_name, version = cmd.get_app_and_version()
+from application_client.solar_command_sender import SolarCommandSender
+from application_client.solar_response_unpacker import (
+ unpack_get_app_and_version_response,
+)
- assert app_name == "Solar"
- assert version == "1.0.0"
+
+# Test a specific APDU asking BOLOS (and not the app) the name and version of the current app
+def test_get_app_and_version(backend, backend_name):
+ # Use the app interface instead of raw interface
+ client = SolarCommandSender(backend)
+ # Send the special instruction to BOLOS
+ response = client.get_app_and_version()
+ # Use an helper to parse the response, assert the values
+ app_name, version = unpack_get_app_and_version_response(response.data)
+
+ assert app_name == "Solar"
+ assert version == "1.1.3"
diff --git a/tests/functional/test_pubkey_cmd.py b/tests/functional/test_pubkey_cmd.py
index 8e6028b6..d9664102 100644
--- a/tests/functional/test_pubkey_cmd.py
+++ b/tests/functional/test_pubkey_cmd.py
@@ -1,62 +1,161 @@
import pytest
-from client.exception import *
-from speculos.client import ApduException
-from client.cmd_builder import InsType
+from application_client.solar_command_sender import SolarCommandSender, Errors
+from application_client.solar_response_unpacker import (
+ unpack_get_public_key_response,
+ unpack_get_public_key_chaincode_response
+)
+from ragger.bip import calculate_public_key_and_chaincode, CurveChoice
+from ragger.error import ExceptionRAPDU
+from ragger.navigator import NavInsID, NavIns
+from utils import ROOT_SCREENSHOT_PATH
-def test_get_public_key(cmd):
- # No Display, No Chain Code
- pub_key, chain_code = cmd.get_public_key(
- bip32_path="44'/3333'/0'/0/0", display=0, chaincode=0
- )
+# In this test we check that the GET_PUBLIC_KEY works in non-confirmation mode
+def test_get_public_key_no_chaincode_no_confirm(backend):
+ client = SolarCommandSender(backend)
+ path = "m/44'/3333'/0'/0/0"
- assert len(pub_key) == 33
- assert len(chain_code) == 0
+ response = client.get_public_key(path=path).data
+ _, public_key = unpack_get_public_key_response(response)
- # Display, No Chain Code
- pub_key2, chain_code2 = cmd.get_public_key(
- bip32_path="44'/3333'/0'/0/0",
- display=1,
- chaincode=0,
- n_screens=5,
+ ref_public_key, _ = calculate_public_key_and_chaincode(
+ CurveChoice.Secp256k1, path=path, compress_public_key=True
)
- assert len(pub_key2) == 33
- assert len(chain_code2) == 0
+ assert public_key.hex() == ref_public_key
+
+
+# In this test we check that the GET_PUBLIC_KEY with a chaincode works in non-confirmation mode
+def test_get_public_key_chaincode_no_confirm(backend):
+ client = SolarCommandSender(backend)
+ path = "m/44'/3333'/0'/0/0"
- # Display, Chain Code
- pub_key3, chain_code3 = cmd.get_public_key(
- bip32_path="44'/3333'/0'/0/0",
- display=1,
- chaincode=1,
- n_screens=5,
+ response = client.get_public_key(path=path, chaincode=1).data
+ _, public_key, _, chain_code = unpack_get_public_key_chaincode_response(response)
+
+ ref_public_key, ref_chain_code = calculate_public_key_and_chaincode(
+ CurveChoice.Secp256k1, path=path, compress_public_key=True
)
- assert len(pub_key3) == 33
- assert len(chain_code3) == 32
+ assert public_key.hex() == ref_public_key
+ assert chain_code.hex() == ref_chain_code
+
+
+# In this test we check that the GET_PUBLIC_KEY works in confirmation mode
+def test_get_public_key_no_chaincode_confirm_accepted(
+ firmware, backend, navigator, test_name
+):
+ client = SolarCommandSender(backend)
+ path = "m/44'/3333'/0'/0/0"
- # No Display, Chain Code
- pub_key4, chain_code4 = cmd.get_public_key(
- bip32_path="44'/3333'/0'/0/0", display=0, chaincode=1
+ with client.get_public_key_with_confirmation(path=path):
+ # if firmware.device.startswith("nano"):
+ navigator.navigate_until_text_and_compare(
+ NavInsID.RIGHT_CLICK,
+ [NavInsID.BOTH_CLICK],
+ "Approve",
+ ROOT_SCREENSHOT_PATH,
+ test_name,
+ )
+ # else: # stax
+ # instructions = [
+ # NavInsID.USE_CASE_REVIEW_TAP,
+ # NavIns(NavInsID.TOUCH, (200, 335)),
+ # NavInsID.USE_CASE_ADDRESS_CONFIRMATION_EXIT_QR,
+ # NavInsID.USE_CASE_ADDRESS_CONFIRMATION_TAP,
+ # NavInsID.USE_CASE_ADDRESS_CONFIRMATION_CONFIRM,
+ # NavInsID.USE_CASE_STATUS_DISMISS
+ # ]
+ # navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH,
+ # test_name,
+ # instructions)
+ response = client.get_async_response().data
+ _, public_key = unpack_get_public_key_response(response)
+
+ ref_public_key, _ = calculate_public_key_and_chaincode(
+ CurveChoice.Secp256k1, path=path, compress_public_key=True
)
- assert len(pub_key4) == 33
- assert len(chain_code4) == 32
+ assert public_key.hex() == ref_public_key
+
+
+# In this test we check that the GET_PUBLIC_KEY with a chaincode works in confirmation mode
+def test_get_public_key_chaincode_confirm_accepted(
+ firmware, backend, navigator, test_name
+):
+ client = SolarCommandSender(backend)
+ path = "m/44'/3333'/0'/0/0"
+
+ with client.get_public_key_with_confirmation(path=path, chaincode=1):
+ # if firmware.device.startswith("nano"):
+ navigator.navigate_until_text_and_compare(
+ NavInsID.RIGHT_CLICK,
+ [NavInsID.BOTH_CLICK],
+ "Approve",
+ ROOT_SCREENSHOT_PATH,
+ test_name,
+ )
+ # else: # stax
+ # instructions = [
+ # NavInsID.USE_CASE_REVIEW_TAP,
+ # NavIns(NavInsID.TOUCH, (200, 335)),
+ # NavInsID.USE_CASE_ADDRESS_CONFIRMATION_EXIT_QR,
+ # NavInsID.USE_CASE_ADDRESS_CONFIRMATION_TAP,
+ # NavInsID.USE_CASE_ADDRESS_CONFIRMATION_CONFIRM,
+ # NavInsID.USE_CASE_STATUS_DISMISS
+ # ]
+ # navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH,
+ # test_name,
+ # instructions)
+ response = client.get_async_response().data
+ _, public_key, _, chain_code = unpack_get_public_key_chaincode_response(response)
+
+ ref_public_key, ref_chain_code = calculate_public_key_and_chaincode(
+ CurveChoice.Secp256k1, path=path, compress_public_key=True
+ )
+ assert public_key.hex() == ref_public_key
+ assert chain_code.hex() == ref_chain_code
-@pytest.mark.xfail(raises=WrongP1P2Error, strict=True)
-def test_wrong_chaincode_option(cmd):
- try:
- cmd.get_public_key(bip32_path="44'/3333'/0'/0/0", display=0, chaincode=2)
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_GET_PUBLIC_KEY)
+# In this test we check that the GET_PUBLIC_KEY in confirmation mode replies an error if the user refuses
+def test_get_public_key_confirm_refused(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+ path = "m/44'/3333'/0'/0/0"
-@pytest.mark.xfail(raises=WrongP1P2Error, strict=True)
-def test_wrong_display_option(cmd):
- try:
- cmd.get_public_key(bip32_path="44'/3333'/0'/0/0", display=2, chaincode=0)
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_GET_PUBLIC_KEY)
+ # if firmware.device.startswith("nano"):
+ with pytest.raises(ExceptionRAPDU) as e:
+ with client.get_public_key_with_confirmation(path=path):
+ navigator.navigate_until_text_and_compare(
+ NavInsID.RIGHT_CLICK,
+ [NavInsID.BOTH_CLICK],
+ "Reject",
+ ROOT_SCREENSHOT_PATH,
+ test_name,
+ )
+ # Assert that we have received a refusal
+ assert e.value.status == Errors.SW_DENY
+ assert len(e.value.data) == 0
+ # else: # stax
+ # instructions_set = [
+ # [
+ # NavInsID.USE_CASE_REVIEW_REJECT,
+ # NavInsID.USE_CASE_STATUS_DISMISS
+ # ],
+ # [
+ # NavInsID.USE_CASE_REVIEW_TAP,
+ # NavInsID.USE_CASE_ADDRESS_CONFIRMATION_CANCEL,
+ # NavInsID.USE_CASE_STATUS_DISMISS
+ # ]
+ # ]
+ # for i, instructions in enumerate(instructions_set):
+ # with pytest.raises(ExceptionRAPDU) as e:
+ # with client.get_public_key_with_confirmation(path=path):
+ # navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH,
+ # test_name + f"/part{i}",
+ # instructions)
+ # # Assert that we have received a refusal
+ # assert e.value.status == Errors.SW_DENY
+ # assert len(e.value.data) == 0
diff --git a/tests/functional/test_sign_cmd.py b/tests/functional/test_sign_cmd.py
deleted file mode 100644
index 15f33634..00000000
--- a/tests/functional/test_sign_cmd.py
+++ /dev/null
@@ -1,326 +0,0 @@
-from btclib.ecc import ssa
-import pytest
-from client.exception import *
-
-from speculos.client import ApduException
-from client.cmd_builder import InsType
-
-from client.transaction import Transaction
-from transactions.multi_signature_registration import Multisignature
-from transactions.ipfs import Ipfs
-from transactions.transfer import Transfer
-from transactions.htlc_lock import HtlcLock
-from transactions.htlc_refund import HtlcRefund
-from transactions.htlc_claim import HtlcClaim
-from transactions.burn import Burn
-from transactions.vote import Vote
-
-
-@pytest.fixture(autouse=True)
-def context(cmd):
- bip32_path: str = "44'/3333'/0'/0/0"
-
- pub_key, chain_code = cmd.get_public_key(
- bip32_path=bip32_path, display=0, chaincode=0
- )
-
- context = {"pkey": pub_key, "chain_code": chain_code, "bip32": bip32_path}
- yield context
-
-
-def test_transfer_tx(cmd, context):
-
- tx = Transfer(
- 1,
- context["pkey"],
- 5645365,
- "This is a test memo.",
- ["3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3"],
- [123456],
- )
- schnorr_sig = cmd.sign_tx(bip32_path=context["bip32"], transaction=tx, n_screens=7)
- assert ssa.verify(tx.serialise(), context["pkey"][1:], schnorr_sig) is True
-
- tx = Transfer(
- 1,
- context["pkey"],
- 5645365,
- "",
- [
- "3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
- "3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
- "3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
- "3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
- "3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
- "3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
- "3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
- "3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
- "3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
- "3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
- "3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
- "3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
- "3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
- "3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
- ],
- [
- 123456,
- 1234567,
- 12345678,
- 123456789,
- 1234567890,
- 12345678900,
- 123456789000,
- 1234567890000,
- 12345678900000,
- 123456789000000,
- 1234567890000000,
- 12345678900000000,
- 123456789000000000,
- 18446744073709551615,
- ],
- )
- schnorr_sig = cmd.sign_tx(bip32_path=context["bip32"], transaction=tx, n_screens=60)
- assert ssa.verify(tx.serialise(), context["pkey"][1:], schnorr_sig) is True
-
-
-@pytest.mark.xfail(raises=TxParsingFailError, strict=True)
-def test_transfer_limit(cmd, context):
-
- tx = Transfer(
- 1,
- context["pkey"],
- 5645365,
- "",
- ["3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3" for _ in range(41)],
- [1 for _ in range(41)],
- )
- cmd.sign_tx(bip32_path=context["bip32"], transaction=tx)
-
-
-def test_burn_tx(cmd, context):
-
- tx = Burn(3, context["pkey"], 0, "", 250000000000)
- schnorr_sig = cmd.sign_tx(bip32_path=context["bip32"], transaction=tx, n_screens=3)
- assert ssa.verify(tx.serialise(), context["pkey"][1:], schnorr_sig) is True
-
-
-def test_htlc_lock_tx(cmd, context):
- tx = HtlcLock(
- 4,
- context["pkey"],
- 645365,
- "",
- 123456789,
- "9c1a3815d49e0c9f78b872bfb017e825ea2db708158b70815526a830c85912b4",
- 1,
- 1234,
- "3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
- )
- schnorr_sig = cmd.sign_tx(bip32_path=context["bip32"], transaction=tx, n_screens=11)
- assert ssa.verify(tx.serialise(), context["pkey"][1:], schnorr_sig) is True
-
-
-def test_htlc_claim_tx(cmd, context):
-
- tx = HtlcClaim(
- 5,
- context["pkey"],
- 645365,
- "",
- 0,
- "cfb37ec05433841cd8d25c3e8d353dc519a6dcb583edd75085b671bff4075b40",
- "c27f1ce845d8c29eebc9006be932b604fd06755521b1a8b0be4204c65377151a",
- )
- schnorr_sig = cmd.sign_tx(bip32_path=context["bip32"], transaction=tx, n_screens=10)
- assert ssa.verify(tx.serialise(), context["pkey"][1:], schnorr_sig) is True
-
-
-def test_htlc_refund_tx(cmd, context):
-
- tx = HtlcRefund(
- 6,
- context["pkey"],
- 645365,
- "",
- "cfb37ec05433841cd8d25c3e8d353dc519a6dcb583edd75085b671bff4075b40",
- )
- schnorr_sig = cmd.sign_tx(bip32_path=context["bip32"], transaction=tx, n_screens=6)
- assert ssa.verify(tx.serialise(), context["pkey"][1:], schnorr_sig) is True
-
-
-def test_ipfs_tx(cmd, context):
-
- tx = Ipfs(
- 7,
- context["pkey"],
- 645365,
- "",
- "122040e8c8cc86493d35f01b603190499ad4046cf2d097f5d34de034cebbba904804",
- )
- schnorr_sig = cmd.sign_tx(bip32_path=context["bip32"], transaction=tx, n_screens=5)
- assert ssa.verify(tx.serialise(), context["pkey"][1:], schnorr_sig) is True
-
-
-def test_multisignature_tx(cmd, context):
-
- tx = Multisignature(
- 8,
- context["pkey"],
- 645365,
- "",
- 2,
- [
- "03e5ea82082ea33c9956ec03109118c7d588f82eb7a0c3c1794de67103bb0c85f9",
- "022f69d427310705c3e02ebb5519bcd545f41a2eed543660fafe0e7191930eb747",
- "03d39fb4797d0c428bebed6d80203e2273a9fdbcaafe0b29761ef3183c2151e211",
- ],
- )
- schnorr_sig = cmd.sign_tx(bip32_path=context["bip32"], transaction=tx, n_screens=15)
- assert ssa.verify(tx.serialise(), context["pkey"][1:], schnorr_sig) is True
-
-
-def test_vote_tx(cmd, context):
-
- tx = Vote(
- 2,
- context["pkey"],
- 10000000,
- "",
- [["gym", 2000], ["cactus1549", 4000], ["sl33p", 4000]],
- )
- schnorr_sig = cmd.sign_tx(bip32_path=context["bip32"], transaction=tx, n_screens=8)
- assert ssa.verify(tx.serialise(), context["pkey"][1:], schnorr_sig) is True
-
- tx = Vote(
- 2,
- context["pkey"],
- 10000000,
- "",
- [],
- )
- schnorr_sig = cmd.sign_tx(bip32_path=context["bip32"], transaction=tx, n_screens=2)
- assert ssa.verify(tx.serialise(), context["pkey"][1:], schnorr_sig) is True
-
-
-@pytest.mark.xfail(raises=TxParsingFailError, strict=True)
-def vote_sum_equal_100(cmd, context):
- try:
- tx = Vote(
- 2,
- context["pkey"],
- 10000000,
- "",
- [["gym", 2001], ["cactus1549", 4000], ["sl33p", 4000]],
- )
- cmd.sign_tx(bip32_path=context["bip32"], transaction=tx, n_screens=2)
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_TX)
-
-
-@pytest.mark.xfail(raises=TxParsingFailError, strict=True)
-def test_accept_v3_only(cmd, context):
- try:
- tx = Transfer(
- 1,
- context["pkey"],
- 5645365,
- "",
- ["3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3"],
- [123456],
- version=2,
- )
- cmd.sign_tx(bip32_path=context["bip32"], transaction=tx)
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_TX)
-
-
-@pytest.mark.xfail(raises=TxParsingFailError, strict=True)
-def test_network_byte(cmd, context):
- try:
- tx = Transfer(
- 1,
- context["pkey"],
- 5645365,
- "",
- ["3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3"],
- [123456],
- network=62,
- )
- cmd.sign_tx(bip32_path=context["bip32"], transaction=tx)
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_TX)
-
-
-@pytest.mark.xfail(raises=TxParsingFailError, strict=True)
-def test_starting_byte(cmd, context):
- try:
- tx = Transfer(
- 1,
- context["pkey"],
- 5645365,
- "",
- ["3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3"],
- [123456],
- startingByte=0xFE,
- )
- cmd.sign_tx(bip32_path=context["bip32"], transaction=tx)
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_TX)
-
-
-@pytest.mark.xfail(raises=TxParsingFailError, strict=True)
-def test_memo_encoding(cmd, context):
- try:
- tx = Transfer(
- 1,
- context["pkey"],
- 5645365,
- "eco\nuter",
- ["3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3"],
- [123456],
- )
- cmd.sign_tx(bip32_path=context["bip32"], transaction=tx)
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_TX)
-
-
-@pytest.mark.xfail(raises=TxParsingFailError, strict=True)
-def test_wrong_typegroup(cmd, context):
- try:
- tx = Transaction(3, 0, 13, context["pkey"], 2000000, "")
- cmd.sign_tx(bip32_path=context["bip32"], transaction=tx)
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_TX)
-
-
-@pytest.mark.xfail(raises=TxParsingFailError, strict=True)
-def test_wrong_type(cmd, context):
- try:
- tx = Transaction(1, 20, 13, context["pkey"], 2000000, "")
- cmd.sign_tx(bip32_path=context["bip32"], transaction=tx)
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_TX)
-
-
-@pytest.mark.xfail(raises=TxParsingFailError, strict=True)
-def test_wrong_memo_length(cmd):
- try:
- cmd.transport.apdu_exchange(
- cla=0xE0,
- ins=0xC2,
- p1=0x00,
- p2=0x80,
- cdata=bytes.fromhex("058000002c80000d05800000000000000000000000"),
- )
-
- cmd.transport.apdu_exchange(
- cla=0xE0,
- ins=0xC2,
- p1=0x01,
- p2=0x00,
- cdata=bytes.fromhex(
- "ff033f010000000600010000000000000002937e1b9294d07c91b46d511851d698ad606a64950dd3a332fcfac9c0a3fb0bad352456000000000005616161616161010040e20100000000003fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3"
- ),
- )
- except ApduException as error:
- raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_TX)
diff --git a/tests/functional/test_sign_message_cmd.py b/tests/functional/test_sign_message_cmd.py
new file mode 100644
index 00000000..4c1b57e9
--- /dev/null
+++ b/tests/functional/test_sign_message_cmd.py
@@ -0,0 +1,119 @@
+import pytest
+
+from ragger.error import ExceptionRAPDU
+from ragger.navigator import NavInsID, NavIns
+from utils import ROOT_SCREENSHOT_PATH
+
+from btclib.ecc import ssa
+
+from application_client.solar_command_sender import (
+ SolarCommandSender,
+ Errors,
+)
+from application_client.solar_response_unpacker import (
+ unpack_get_public_key_response,
+)
+from constants import PATH_MAINNET
+
+
+MESSAGE_SHORT: str = "We are the music makers,\n the dreamers of dreams...\n"
+MESSAGE_LONG: str = "A long, long time ago the World was in an age of Chaos. In the midst of the chaos, in a little kingdom in the land of Hyrule, a legend was being handed down from generation to generation, the legend of the 'Triforce': golden triangles possessing mystical powers. One day, an evil army led by Ganon, the powerful Prince of Darkness, attacked and stole the Triforce of Power. Fearing his wicked rule, princess Zelda split the Triforce of Wisdom into eight fragments and hid them throughout the realm. She commanded her most trustworthy nursemaid, Impa, to escape and search for someone courageous enough to destroy the evil Ganon. Upon hearing this, Ganon grew angry, imprisoned the princess, and sent out a party in search of Impa. Braving forests and mountains, Impa fled for her life from her pursuers. As she reached the very limit of her energy she found herself surrounded by Ganon's evil henchmen. Cornered! What could she do? But wait! All was not lost. A young lad appeared, driving off Ganon's henchmen and saving Impa from a fate worse than death. His name was Link. Impa told Link the story of Zelda and the evil Ganon. Burning with a sense of justice, Link resolved to save Zelda. But Ganon was a powerful opponent. He held the Triforce of Power. Link had to bring the scattered eight fragments of the Triforce of Wisdom together to rebuild the mystical triangle or there would be no chance he could fight his way into Death Mountain where Ganon lived. Can Link really destroy Ganon and save princess Zelda? Only your skill can answer that question. Good luck. Use the Triforce wisely."
+
+
+# In this tests we check the behaviour of the device when asked to sign a short message
+def test_sign_message_short(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ rapdu = client.get_public_key(path=PATH_MAINNET)
+ _, public_key = unpack_get_public_key_response(rapdu.data)
+
+ with client.sign_message(path=PATH_MAINNET, message=MESSAGE_SHORT):
+ # if firmware.device.startswith("nano"):
+ navigator.navigate_until_text_and_compare(
+ NavInsID.RIGHT_CLICK,
+ [NavInsID.BOTH_CLICK],
+ "Approve",
+ ROOT_SCREENSHOT_PATH,
+ test_name,
+ )
+ # else:
+ # navigator.navigate_until_text_and_compare(NavInsID.USE_CASE_REVIEW_TAP,
+ # [NavInsID.USE_CASE_REVIEW_CONFIRM,
+ # NavInsID.USE_CASE_STATUS_DISMISS],
+ # "Hold to sign",
+ # ROOT_SCREENSHOT_PATH,
+ # test_name)
+ response = client.get_async_response().data
+
+ msg_short: bytes = b"".join(
+ [len(MESSAGE_SHORT).to_bytes(2, byteorder="little"), bytes(MESSAGE_SHORT, "ascii")]
+ )
+
+ assert ssa.verify(msg_short, public_key, response) is True
+
+
+# In this tests we check the behaviour of the device when asked to sign a long message
+def test_sign_message_long(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ # First we need to get the public key of the device in order to build the transaction
+ rapdu = client.get_public_key(path=PATH_MAINNET)
+ _, public_key = unpack_get_public_key_response(rapdu.data)
+
+ with client.sign_message(path=PATH_MAINNET, message=MESSAGE_LONG):
+ # if firmware.device.startswith("nano"):
+ navigator.navigate_until_text_and_compare(
+ NavInsID.RIGHT_CLICK,
+ [NavInsID.BOTH_CLICK],
+ "Approve",
+ ROOT_SCREENSHOT_PATH,
+ test_name,
+ )
+ # else:
+ # navigator.navigate_until_text_and_compare(NavInsID.USE_CASE_REVIEW_TAP,
+ # [NavInsID.USE_CASE_REVIEW_CONFIRM,
+ # NavInsID.USE_CASE_STATUS_DISMISS],
+ # "Hold to sign",
+ # ROOT_SCREENSHOT_PATH,
+ # test_name)
+ response = client.get_async_response().data
+
+ msg_long: bytes = b"".join(
+ [len(MESSAGE_LONG).to_bytes(2, byteorder="little"), bytes(MESSAGE_LONG, "ascii")]
+ )
+
+ assert ssa.verify(msg_long, public_key, response) is True
+
+
+# Message signature refused test
+# The test will ask for a message signature that will be refused on screen
+def test_sign_message_refused(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ # if firmware.device.startswith("nano"):
+ with pytest.raises(ExceptionRAPDU) as e:
+ with client.sign_message(path=PATH_MAINNET, message=MESSAGE_SHORT):
+ # if firmware.device.startswith("nano"):
+ navigator.navigate_until_text_and_compare(
+ NavInsID.RIGHT_CLICK,
+ [NavInsID.BOTH_CLICK],
+ "Reject",
+ ROOT_SCREENSHOT_PATH,
+ test_name,
+ )
+ assert e.value.status == Errors.SW_DENY
+ assert len(e.value.data) == 0
+ # else:
+ # for i in range(3):
+ # instructions = [NavInsID.USE_CASE_REVIEW_TAP] * i
+ # instructions += [NavInsID.USE_CASE_REVIEW_REJECT,
+ # NavInsID.USE_CASE_CHOICE_CONFIRM,
+ # NavInsID.USE_CASE_STATUS_DISMISS]
+ # with pytest.raises(ExceptionRAPDU) as e:
+ # with client.sign_tx(path=PATH_MAINNET, transaction=transaction):
+ # navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH,
+ # test_name + f"/part{i}",
+ # instructions)
+ # # Assert that we have received a refusal
+ # assert e.value.status == Errors.SW_DENY
+ # assert len(e.value.data) == 0
diff --git a/tests/functional/test_sign_transaction_cmd.py b/tests/functional/test_sign_transaction_cmd.py
new file mode 100644
index 00000000..d00b7851
--- /dev/null
+++ b/tests/functional/test_sign_transaction_cmd.py
@@ -0,0 +1,549 @@
+import pytest
+
+from ragger.error import ExceptionRAPDU
+from ragger.navigator import NavInsID, NavIns
+from utils import ROOT_SCREENSHOT_PATH
+
+from btclib.ecc import ssa
+
+from application_client.solar_command_sender import (
+ CLA,
+ InsType,
+ P1,
+ P2,
+ MAX_APDU_LEN,
+ SolarCommandSender,
+ split_message,
+ Errors,
+)
+from application_client.solar_response_unpacker import (
+ unpack_get_public_key_response,
+)
+from transactions.transfer import Transfer
+from transactions.vote import Vote
+from transactions.burn import Burn
+from transactions.ipfs import Ipfs
+from application_client.solar_transaction import (
+ Transaction,
+)
+from constants import PATH_MAINNET
+
+
+# Check the behaviour of the device when asked to sign an ipfs transaction.
+# TypeGroup 1, Type 5
+def test_sign_transaction_ipfs(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ rapdu = client.get_public_key(path=PATH_MAINNET)
+ _, public_key = unpack_get_public_key_response(rapdu.data)
+
+ ipfs_transaction = Ipfs(
+ nonce=1,
+ senderPkey=public_key,
+ fee=645365,
+ memo="",
+ ipfs="122040e8c8cc86493d35f01b603190499ad4046cf2d097f5d34de034cebbba904804",
+ )
+
+ with client.sign_transaction(path=PATH_MAINNET, transaction=ipfs_transaction):
+ # if firmware.device.startswith("nano"):
+ navigator.navigate_until_text_and_compare(
+ NavInsID.RIGHT_CLICK,
+ [NavInsID.BOTH_CLICK],
+ "Approve",
+ ROOT_SCREENSHOT_PATH,
+ test_name,
+ )
+ # else:
+ # navigator.navigate_until_text_and_compare(NavInsID.USE_CASE_REVIEW_TAP,
+ # [NavInsID.USE_CASE_REVIEW_CONFIRM,
+ # NavInsID.USE_CASE_STATUS_DISMISS],
+ # "Hold to sign",
+ # ROOT_SCREENSHOT_PATH,
+ # test_name)
+ response = client.get_async_response().data
+
+ assert ssa.verify(ipfs_transaction.serialise(), public_key, response) is True
+
+
+# Check the behaviour of the device when asked to sign a transfer transaction.
+# TypeGroup 1, Type 6
+def test_sign_transaction_transfer(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ rapdu = client.get_public_key(path=PATH_MAINNET)
+ _, public_key = unpack_get_public_key_response(rapdu.data)
+
+ transfer_transaction = Transfer(
+ nonce=2,
+ senderPkey=public_key,
+ fee=5645365,
+ memo="This is an optional memo.",
+ addresses=[
+ "3f091327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
+ "3f192327b917bf2b464e9b8f1acf1588f4cb6e7bb3",
+ "3f293327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
+ "3f394327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
+ "3f495327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
+ "3f596327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
+ "3f697327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
+ "3f798327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
+ "3f899327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
+ "3f990327b917bf2b464e9b8f1acf0588f4cb6e7bb3",
+ "3fa91427b917bf2b464e9b8f1acf0588f4cb6e7bb3",
+ "3fb91527b917bf2b464e9b8f1acf0588f4cb6e7bb3",
+ "3fc91627b917bf2b464e9b8f1acf0588f4cb6e7bb3",
+ "3fd91727b917bf2b464e9b8f1acf0588f4cb6e7bb3",
+ ],
+ amounts=[
+ 123456,
+ 1234567,
+ 12345678,
+ 123456789,
+ 1234567890,
+ 12345678900,
+ 123456789000,
+ 1234567890000,
+ 12345678900000,
+ 123456789000000,
+ 1234567890000000,
+ 12345678900000000,
+ 123456789000000000,
+ 18446744073709551615,
+ ],
+ )
+
+ with client.sign_transaction(path=PATH_MAINNET, transaction=transfer_transaction):
+ # if firmware.device.startswith("nano"):
+ navigator.navigate_until_text_and_compare(
+ NavInsID.RIGHT_CLICK,
+ [NavInsID.BOTH_CLICK],
+ "Approve",
+ ROOT_SCREENSHOT_PATH,
+ test_name,
+ )
+ # else:
+ # navigator.navigate_until_text_and_compare(NavInsID.USE_CASE_REVIEW_TAP,
+ # [NavInsID.USE_CASE_REVIEW_CONFIRM,
+ # NavInsID.USE_CASE_STATUS_DISMISS],
+ # "Hold to sign",
+ # ROOT_SCREENSHOT_PATH,
+ # test_name)
+ response = client.get_async_response().data
+
+ assert ssa.verify(transfer_transaction.serialise(), public_key, response) is True
+
+
+# Check the behaviour of the device when asked to sign a burn transaction.
+# TypeGroup 2, Type 0
+def test_sign_transaction_burn(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ rapdu = client.get_public_key(path=PATH_MAINNET)
+ _, public_key = unpack_get_public_key_response(rapdu.data)
+
+ burn_transaction = Burn(
+ nonce=3,
+ senderPkey=public_key,
+ fee=10000000,
+ memo="",
+ amount=250000000000,
+ )
+
+ with client.sign_transaction(path=PATH_MAINNET, transaction=burn_transaction):
+ # if firmware.device.startswith("nano"):
+ navigator.navigate_until_text_and_compare(
+ NavInsID.RIGHT_CLICK,
+ [NavInsID.BOTH_CLICK],
+ "Approve",
+ ROOT_SCREENSHOT_PATH,
+ test_name,
+ )
+ # else:
+ # navigator.navigate_until_text_and_compare(NavInsID.USE_CASE_REVIEW_TAP,
+ # [NavInsID.USE_CASE_REVIEW_CONFIRM,
+ # NavInsID.USE_CASE_STATUS_DISMISS],
+ # "Hold to sign",
+ # ROOT_SCREENSHOT_PATH,
+ # test_name)
+ response = client.get_async_response().data
+
+ assert ssa.verify(burn_transaction.serialise(), public_key, response) is True
+
+
+# Check the behaviour of the device when asked to sign a vote transaction.
+# TypeGroup 2, Type 2
+def test_sign_transaction_vote(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ rapdu = client.get_public_key(path=PATH_MAINNET)
+ _, public_key = unpack_get_public_key_response(rapdu.data)
+
+ vote_transaction = Vote(
+ nonce=4,
+ senderPkey=public_key,
+ fee=10000000,
+ memo="",
+ votes=[["gym", 2000], ["cactus1549", 4000], ["sl33p", 4000]],
+ )
+
+ with client.sign_transaction(path=PATH_MAINNET, transaction=vote_transaction):
+ # if firmware.device.startswith("nano"):
+ navigator.navigate_until_text_and_compare(
+ NavInsID.RIGHT_CLICK,
+ [NavInsID.BOTH_CLICK],
+ "Approve",
+ ROOT_SCREENSHOT_PATH,
+ test_name,
+ )
+ # else:
+ # navigator.navigate_until_text_and_compare(NavInsID.USE_CASE_REVIEW_TAP,
+ # [NavInsID.USE_CASE_REVIEW_CONFIRM,
+ # NavInsID.USE_CASE_STATUS_DISMISS],
+ # "Hold to sign",
+ # ROOT_SCREENSHOT_PATH,
+ # test_name)
+ response = client.get_async_response().data
+
+ assert ssa.verify(vote_transaction.serialise(), public_key, response) is True
+
+
+# Check the behaviour of the device when asked to sign a cancel vote transaction.
+# TypeGroup 2, Type 2
+def test_sign_transaction_vote_cancel(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ rapdu = client.get_public_key(path=PATH_MAINNET)
+ _, public_key = unpack_get_public_key_response(rapdu.data)
+
+ cancel_vote_transaction = Vote(
+ nonce=5,
+ senderPkey=public_key,
+ fee=10000000,
+ memo="",
+ votes=[],
+ )
+
+ with client.sign_transaction(path=PATH_MAINNET, transaction=cancel_vote_transaction):
+ # if firmware.device.startswith("nano"):
+ navigator.navigate_until_text_and_compare(
+ NavInsID.RIGHT_CLICK,
+ [NavInsID.BOTH_CLICK],
+ "Approve",
+ ROOT_SCREENSHOT_PATH,
+ test_name,
+ )
+ # else:
+ # navigator.navigate_until_text_and_compare(NavInsID.USE_CASE_REVIEW_TAP,
+ # [NavInsID.USE_CASE_REVIEW_CONFIRM,
+ # NavInsID.USE_CASE_STATUS_DISMISS],
+ # "Hold to sign",
+ # ROOT_SCREENSHOT_PATH,
+ # test_name)
+ response = client.get_async_response().data
+
+ assert ssa.verify(cancel_vote_transaction.serialise(), public_key, response) is True
+
+
+# Check the behaviour of the device when the transfer uses an invalid typegroup.
+def test_sign_transaction_type_group_invalid(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ rapdu = client.get_public_key(path=PATH_MAINNET)
+ _, public_key = unpack_get_public_key_response(rapdu.data)
+
+ transaction = Transaction(
+ typeGroup=3,
+ type=0,
+ nonce=6,
+ senderPkey=public_key,
+ fee=2000000,
+ memo="",
+ )
+
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START,
+ p2=P2.P2_MORE,
+ data=bytes.fromhex("058000002c80000d05800000000000000000000000"),
+ )
+
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START + 1,
+ p2=P2.P2_LAST,
+ data=transaction.serialise(),
+ )
+ assert e.value.status == Errors.SW_TX_PARSING_FAIL
+
+
+# Check the behaviour of the device when the transfer uses an invalid type.
+def test_sign_transaction_type_invalid(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ rapdu = client.get_public_key(path=PATH_MAINNET)
+ _, public_key = unpack_get_public_key_response(rapdu.data)
+
+ transaction = Transaction(
+ typeGroup=20,
+ type=20,
+ nonce=6,
+ senderPkey=public_key,
+ fee=2000000,
+ memo="",
+ )
+
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START,
+ p2=P2.P2_MORE,
+ data=bytes.fromhex("058000002c80000d05800000000000000000000000"),
+ )
+
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START + 1,
+ p2=P2.P2_LAST,
+ data=transaction.serialise(),
+ )
+ assert e.value.status == Errors.SW_TX_PARSING_FAIL
+
+# Check the behaviour of the device when the transfer limit is exceeded.
+def test_sign_transfer_limit_exceeded(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ rapdu = client.get_public_key(path=PATH_MAINNET)
+ _, public_key = unpack_get_public_key_response(rapdu.data)
+
+ transfer_transaction = Transfer(
+ nonce=2,
+ senderPkey=public_key,
+ fee=5645365,
+ memo="",
+ addresses=["3fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3" for _ in range(41)],
+ amounts=[1 for _ in range(41)],
+ )
+
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START,
+ p2=P2.P2_MORE,
+ data=bytes.fromhex("058000002c80000d05800000000000000000000000"),
+ )
+ chunks = split_message(transfer_transaction.serialise(), MAX_APDU_LEN)
+ idx: int = P1.P1_START + 1
+
+ for chunk in chunks:
+ backend.exchange(
+ cla=CLA, ins=InsType.SIGN_TX, p1=idx, p2=P2.P2_MORE, data=chunk
+ )
+ idx += 1
+
+ assert e.value.status == Errors.SW_WRONG_TX_LENGTH
+
+
+# Check the behaviour of the device when the transfer uses an unsupported version.
+def test_sign_transfer_version_unsupported(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ rapdu = client.get_public_key(path=PATH_MAINNET)
+ _, public_key = unpack_get_public_key_response(rapdu.data)
+
+ transfer_transaction = Transfer(
+ version=2,
+ nonce=2,
+ senderPkey=public_key,
+ fee=5645365,
+ memo="",
+ addresses=["3f091327b917bf2b464e9b8f1acf0588f4cb6e7bb3"],
+ amounts=[123456],
+ )
+
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START,
+ p2=P2.P2_MORE,
+ data=bytes.fromhex("058000002c80000d05800000000000000000000000"),
+ )
+
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START + 1,
+ p2=P2.P2_LAST,
+ data=transfer_transaction.serialise(),
+ )
+ assert e.value.status == Errors.SW_TX_PARSING_FAIL
+
+
+# Check the behaviour of the device when the transfer uses an unsupported network.
+def test_sign_transfer_network_unsupported(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ rapdu = client.get_public_key(path=PATH_MAINNET)
+ _, public_key = unpack_get_public_key_response(rapdu.data)
+
+ transfer_transaction = Transfer(
+ network=62,
+ nonce=2,
+ senderPkey=public_key,
+ fee=5645365,
+ memo="",
+ addresses=["3f091327b917bf2b464e9b8f1acf0588f4cb6e7bb3"],
+ amounts=[123456],
+ )
+
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START,
+ p2=P2.P2_MORE,
+ data=bytes.fromhex("058000002c80000d05800000000000000000000000"),
+ )
+
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START + 1,
+ p2=P2.P2_LAST,
+ data=transfer_transaction.serialise(),
+ )
+ assert e.value.status == Errors.SW_TX_PARSING_FAIL
+
+
+# Check the behaviour of the device when the transfer uses an invalid starting byte.
+def test_sign_transfer_starting_byte_invalid(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ rapdu = client.get_public_key(path=PATH_MAINNET)
+ _, public_key = unpack_get_public_key_response(rapdu.data)
+
+ transfer_transaction = Transfer(
+ startingByte=0xFE,
+ nonce=2,
+ senderPkey=public_key,
+ fee=5645365,
+ memo="",
+ addresses=["3f091327b917bf2b464e9b8f1acf0588f4cb6e7bb3"],
+ amounts=[123456],
+ )
+
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START,
+ p2=P2.P2_MORE,
+ data=bytes.fromhex("058000002c80000d05800000000000000000000000"),
+ )
+
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START + 1,
+ p2=P2.P2_LAST,
+ data=transfer_transaction.serialise(),
+ )
+ assert e.value.status == Errors.SW_TX_PARSING_FAIL
+
+
+# Check the behaviour of the device when the transfer uses an invalid memo encoding.
+def test_sign_transfer_memo_invalid(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ rapdu = client.get_public_key(path=PATH_MAINNET)
+ _, public_key = unpack_get_public_key_response(rapdu.data)
+
+ transfer_transaction = Transfer(
+ nonce=2,
+ senderPkey=public_key,
+ fee=5645365,
+ memo="this\nis\nnot\nvalid",
+ addresses=["3f091327b917bf2b464e9b8f1acf0588f4cb6e7bb3"],
+ amounts=[123456],
+ )
+
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START,
+ p2=P2.P2_MORE,
+ data=bytes.fromhex("058000002c80000d05800000000000000000000000"),
+ )
+
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START + 1,
+ p2=P2.P2_LAST,
+ data=transfer_transaction.serialise(),
+ )
+ assert e.value.status == Errors.SW_TX_PARSING_FAIL
+
+
+# Check the behaviour of the device when the data length is invalid.
+def test_transaction_data_length_invalid(backend):
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START,
+ p2=P2.P2_MORE,
+ )
+
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START + 1,
+ p2=P2.P2_LAST,
+ data=bytes.fromhex(
+ "ff033f010000000600010000000000000002937e1b9294d07c91b46d511851d698ad606a64950dd3a332fcfac9c0a3fb0bad352456000000000005616161616161010040e20100000000003fc91327b917bf2b464e9b8f1acf0588f4cb6e7bb3"
+ ),
+ )
+ assert e.value.status == Errors.SW_WRONG_DATA_LENGTH
+
+
+# Check the behaviour of the device when the transfer uses an invalid vote sum.
+def test_sign_transfer_vote_sum_invalid(firmware, backend, navigator, test_name):
+ client = SolarCommandSender(backend)
+
+ rapdu = client.get_public_key(path=PATH_MAINNET)
+ _, public_key = unpack_get_public_key_response(rapdu.data)
+
+ vote_transaction = Vote(
+ nonce=6,
+ senderPkey=public_key,
+ fee=10000000,
+ memo="",
+ votes=[["gym", 2001], ["cactus1549", 4000], ["sl33p", 4000]],
+ )
+
+ with pytest.raises(ExceptionRAPDU) as e:
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START,
+ p2=P2.P2_MORE,
+ data=bytes.fromhex("058000002c80000d05800000000000000000000000"),
+ )
+
+ backend.exchange(
+ cla=CLA,
+ ins=InsType.SIGN_TX,
+ p1=P1.P1_START + 1,
+ p2=P2.P2_LAST,
+ data=vote_transaction.serialise(),
+ )
+ assert e.value.status == Errors.SW_TX_PARSING_FAIL
diff --git a/tests/functional/test_status_word.py b/tests/functional/test_status_word.py
deleted file mode 100644
index 0a492f09..00000000
--- a/tests/functional/test_status_word.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from pathlib import Path
-from typing import List, Dict, Any, Tuple
-import re
-
-from client.exception import DeviceException
-
-
-SW_RE = re.compile(r"""(?x)
- \# # character '#'
- define # string 'define'
- \s+ # spaces
- (?PSW(?:_[A-Z0-9]+)*) # identifier (e.g. 'SW_OK')
- \s+ # spaces
- 0x(?P[a-fA-F0-9]{4}) # 4 bytes status word
-""")
-
-
-def parse_sw(path: Path) -> List[Tuple[str, int]]:
- if not path.is_file():
- raise FileNotFoundError(f"Can't find file: '{path}'")
-
- sw_h: str = path.read_text()
-
- return [(identifier, int(sw, base=16))
- for identifier, sw in SW_RE.findall(sw_h) if sw != "9000"]
-
-
-def test_status_word(sw_h_path):
- expected_status_words: List[Tuple[str, int]] = parse_sw(sw_h_path)
- status_words: Dict[int, Any] = DeviceException.exc
-
- assert len(expected_status_words) == len(status_words), (
- f"{expected_status_words} doesn't match {status_words}")
-
- # just keep status words
- expected_status_words = [sw for (identifier, sw) in expected_status_words]
-
- for sw in status_words.keys():
- assert sw in expected_status_words, f"{status_words[sw]}({hex(sw)}) not found in sw.h!"
diff --git a/tests/functional/test_version_cmd.py b/tests/functional/test_version_cmd.py
index 6d18ce6a..f5acb374 100644
--- a/tests/functional/test_version_cmd.py
+++ b/tests/functional/test_version_cmd.py
@@ -1,2 +1,17 @@
-def test_version(cmd):
- assert cmd.get_version() == (1, 0, 0)
+from application_client.solar_command_sender import SolarCommandSender
+from application_client.solar_response_unpacker import unpack_get_version_response
+
+
+# Taken from the Makefile, to update every time the Makefile version is bumped
+MAJOR = 1
+MINOR = 1
+PATCH = 3
+
+# In this test we check the behaviour of the device when asked to provide the app version
+def test_version(backend):
+ # Use the app interface instead of raw interface
+ client = SolarCommandSender(backend)
+ # Send the GET_VERSION instruction
+ rapdu = client.get_version()
+ # Use an helper to parse the response, assert the values
+ assert unpack_get_version_response(rapdu.data) == (MAJOR, MINOR, PATCH)
diff --git a/tests/functional/transactions/burn.py b/tests/functional/transactions/burn.py
index 4ec6a124..b1567fdd 100644
--- a/tests/functional/transactions/burn.py
+++ b/tests/functional/transactions/burn.py
@@ -1,7 +1,7 @@
from typing import Union
-from client.utils import UINT64_MAX
-from client.transaction import Transaction, TransactionError
+from application_client.solar_utils import UINT64_MAX
+from application_client.solar_transaction import Transaction, TransactionError
class Burn(Transaction):
diff --git a/tests/functional/transactions/htlc_claim.py b/tests/functional/transactions/htlc_claim.py
deleted file mode 100644
index 1f8a7b20..00000000
--- a/tests/functional/transactions/htlc_claim.py
+++ /dev/null
@@ -1,53 +0,0 @@
-from typing import Union
-
-from client.utils import UINT8_MAX
-from client.transaction import Transaction, TransactionError
-
-
-class HtlcClaim(Transaction):
- def __init__(
- self,
- nonce: int,
- senderPkey: Union[str, bytes],
- fee: int,
- memo: str,
- hashType: int,
- lockId: Union[str, bytes],
- unlockSecret: Union[str, bytes],
- network: int = 63,
- version: int = 3,
- startingByte: int = 0xFF,
- ) -> None:
- super().__init__(
- 1, 9, nonce, senderPkey, fee, memo, network, version, startingByte
- )
-
- self.hashType: int = hashType
-
- self.lockId: bytes = (
- bytes.fromhex(lockId) if isinstance(lockId, str) else lockId
- )
- self.unlockSecret: bytes = (
- bytes.fromhex(unlockSecret)
- if isinstance(unlockSecret, str)
- else unlockSecret
- )
-
- if not (0 <= self.hashType <= UINT8_MAX):
- raise TransactionError(f"Bad amount: '{self.amount}'!")
-
- if len(self.lockId) != 32:
- raise TransactionError(f"Bad lockId: '{self.lockId}'!")
-
- if len(self.unlockSecret) > UINT8_MAX:
- raise TransactionError(f"Bad unlockSecret: '{self.unlockSecret}'!")
-
- def serialise(self) -> bytes:
- return super().serialise() + b"".join(
- [
- self.hashType.to_bytes(1, byteorder="little"),
- self.lockId,
- len(self.unlockSecret).to_bytes(1, byteorder="little"),
- self.unlockSecret,
- ]
- )
diff --git a/tests/functional/transactions/htlc_lock.py b/tests/functional/transactions/htlc_lock.py
deleted file mode 100644
index e5bb5920..00000000
--- a/tests/functional/transactions/htlc_lock.py
+++ /dev/null
@@ -1,61 +0,0 @@
-from typing import Union
-
-from client.utils import UINT64_MAX, UINT32_MAX, UINT8_MAX
-from client.transaction import Transaction, TransactionError
-
-
-class HtlcLock(Transaction):
- def __init__(
- self,
- nonce: int,
- senderPkey: Union[str, bytes],
- fee: int,
- memo: str,
- amount: int,
- secretHash: Union[str, bytes],
- expirationType: int,
- expirationValue: int,
- recipientId: Union[str, bytes],
- network: int = 63,
- version: int = 3,
- startingByte: int = 0xFF,
- ) -> None:
- super().__init__(
- 1, 8, nonce, senderPkey, fee, memo, network, version, startingByte
- )
- self.amount: int = amount
- self.secretHash: bytes = (
- bytes.fromhex(secretHash) if isinstance(secretHash, str) else secretHash
- )
- self.expirationType: int = expirationType
- self.expirationValue: int = expirationValue
- self.recipientId: bytes = (
- bytes.fromhex(recipientId) if isinstance(recipientId, str) else recipientId
- )
-
- if not (0 <= self.amount <= UINT64_MAX):
- raise TransactionError(f"Bad amount: '{self.amount}'!")
-
- if len(self.secretHash) > UINT8_MAX:
- raise TransactionError(f"Bad secretHash: '{self.secretHash}'!")
-
- if not (0 <= self.expirationType <= UINT8_MAX):
- raise TransactionError(f"Bad expirationType: '{self.expirationType}'!")
-
- if not (0 <= self.expirationValue <= UINT32_MAX):
- raise TransactionError(f"Bad expirationValue: '{self.expirationValue}'!")
-
- if len(self.recipientId) != 21:
- raise TransactionError(f"Bad recipientId: '{self.recipientId}'!")
-
- def serialise(self) -> bytes:
- return super().serialise() + b"".join(
- [
- self.amount.to_bytes(8, byteorder="little"),
- len(self.secretHash).to_bytes(1, byteorder="little"),
- self.secretHash,
- self.expirationType.to_bytes(1, byteorder="little"),
- self.expirationValue.to_bytes(4, byteorder="little"),
- self.recipientId,
- ]
- )
diff --git a/tests/functional/transactions/htlc_refund.py b/tests/functional/transactions/htlc_refund.py
deleted file mode 100644
index b17d3dae..00000000
--- a/tests/functional/transactions/htlc_refund.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from typing import Union
-
-from client.utils import UINT64_MAX
-from client.transaction import Transaction, TransactionError
-
-
-class HtlcRefund(Transaction):
- def __init__(
- self,
- nonce: int,
- senderPkey: Union[str, bytes],
- fee: int,
- memo: str,
- lockId: Union[str, bytes],
- network: int = 63,
- version: int = 3,
- startingByte: int = 0xFF,
- ) -> None:
- super().__init__(
- 1, 10, nonce, senderPkey, fee, memo, network, version, startingByte
- )
- self.lockId: bytes = (
- bytes.fromhex(lockId) if isinstance(lockId, str) else lockId
- )
-
- if len(self.lockId) != 32:
- raise TransactionError(f"Bad lockId: '{self.lockId}'!")
-
- def serialise(self) -> bytes:
- return super().serialise() + b"".join([self.lockId])
diff --git a/tests/functional/transactions/ipfs.py b/tests/functional/transactions/ipfs.py
index f4427376..c32036c3 100644
--- a/tests/functional/transactions/ipfs.py
+++ b/tests/functional/transactions/ipfs.py
@@ -1,7 +1,7 @@
from typing import Union
-from client.utils import UINT64_MAX
-from client.transaction import Transaction, TransactionError
+from application_client.solar_utils import UINT64_MAX
+from application_client.solar_transaction import Transaction, TransactionError
class Ipfs(Transaction):
diff --git a/tests/functional/transactions/multi_signature_registration.py b/tests/functional/transactions/multi_signature_registration.py
deleted file mode 100644
index 3df18aca..00000000
--- a/tests/functional/transactions/multi_signature_registration.py
+++ /dev/null
@@ -1,43 +0,0 @@
-from typing import Union, List
-
-from client.utils import write_varint, UINT8_MAX
-from client.transaction import Transaction, TransactionError
-
-
-class Multisignature(Transaction):
- def __init__(
- self,
- nonce: int,
- senderPkey: Union[str, bytes],
- fee: int,
- memo: str,
- min: int,
- pkeys: List[Union[bytes, str]],
- network: int = 63,
- version: int = 3,
- startingByte: int = 0xFF,
- ) -> None:
- super().__init__(
- 1, 4, nonce, senderPkey, fee, memo, network, version, startingByte
- )
- self.min: int = min
- self.pkeys = []
- for key in pkeys:
- if len(key) != 66:
- raise TransactionError(f"Bad pkeys: '{key}'!")
- self.pkeys.append(bytes.fromhex(key) if isinstance(key, str) else key)
-
- if not (0 <= self.min <= UINT8_MAX):
- raise TransactionError(f"Bad min: '{self.min}'!")
-
- if len(self.pkeys) < 1 or len(self.pkeys) > 16:
- raise TransactionError(f"Bad pkeys: '{self.pkeys}'!")
-
- def serialise(self) -> bytes:
- return super().serialise() + b"".join(
- [
- self.min.to_bytes(1, byteorder="little"),
- write_varint(len(self.pkeys)),
- *self.pkeys,
- ]
- )
diff --git a/tests/functional/transactions/transfer.py b/tests/functional/transactions/transfer.py
index 8ba09353..ad7d0418 100644
--- a/tests/functional/transactions/transfer.py
+++ b/tests/functional/transactions/transfer.py
@@ -1,7 +1,7 @@
from typing import Union, List
-from client.utils import write_varint, UINT64_MAX
-from client.transaction import Transaction, TransactionError
+from application_client.solar_utils import write_varint, UINT64_MAX
+from application_client.solar_transaction import Transaction, TransactionError
class Transfer(Transaction):
diff --git a/tests/functional/transactions/vote.py b/tests/functional/transactions/vote.py
index ccfade64..4d33e5d7 100644
--- a/tests/functional/transactions/vote.py
+++ b/tests/functional/transactions/vote.py
@@ -1,7 +1,7 @@
from typing import Union, List
-from client.utils import UINT16_MAX
-from client.transaction import Transaction, TransactionError
+from application_client.solar_utils import UINT16_MAX
+from application_client.solar_transaction import Transaction, TransactionError
class Vote(Transaction):
diff --git a/tests/functional/utils.py b/tests/functional/utils.py
new file mode 100644
index 00000000..79c5ac30
--- /dev/null
+++ b/tests/functional/utils.py
@@ -0,0 +1,4 @@
+from pathlib import Path
+
+# Used by Ragger navigator for snapshot validation
+ROOT_SCREENSHOT_PATH = Path(__file__).parent.resolve()
diff --git a/tests/unit-tests/CMakeLists.txt b/tests/unit-tests/CMakeLists.txt
index 670ef02b..73e6351b 100644
--- a/tests/unit-tests/CMakeLists.txt
+++ b/tests/unit-tests/CMakeLists.txt
@@ -6,8 +6,8 @@ endif()
# project information
project(unit_tests
- VERSION 0.1
- DESCRIPTION "Unit tests for Ledger Nano application"
+ VERSION 1.1.3
+ DESCRIPTION "Unit tests for Ledger Nano application"
LANGUAGES C)
@@ -35,47 +35,38 @@ endif()
add_compile_definitions(TEST)
-add_definitions(-DNANO_PXLS_PER_LINE=114 -DIS_NANOS=1)
+if(TARGET_NAME STREQUAL "TARGET_NANOS")
+ add_definitions(-DTARGET_NANOS=1)
+endif()
include_directories(../../src)
-add_executable(test_base58 test_base58.c)
-add_executable(test_bip32 test_bip32.c)
-add_executable(test_buffer test_buffer.c)
-add_executable(test_format test_format.c)
-add_executable(test_write test_write.c)
-add_executable(test_apdu_parser test_apdu_parser.c)
add_executable(test_tx_parser test_tx_parser.c)
add_executable(test_tx_utils test_tx_utils.c)
add_library(nano_char_table nano_char_table.c)
-
-add_library(base58 SHARED ../../src/common/base58.c)
-add_library(bip32 SHARED ../../src/common/bip32.c)
-add_library(buffer SHARED ../../src/common/buffer.c)
-add_library(read SHARED ../../src/common/read.c)
-add_library(write SHARED ../../src/common/write.c)
-add_library(format SHARED ../../src/common/format.c)
-add_library(varint SHARED ../../src/common/varint.c)
-add_library(apdu_parser SHARED ../../src/apdu/parser.c)
+include_directories(
+ $ENV{BOLOS_SDK}/include
+ $ENV{BOLOS_SDK}/lib_standard_app
+)
+
+add_library(base58 SHARED $ENV{BOLOS_SDK}/lib_standard_app/base58.c)
+add_library(bip32 SHARED $ENV{BOLOS_SDK}/lib_standard_app/bip32.c)
+add_library(buffer SHARED $ENV{BOLOS_SDK}/lib_standard_app/buffer.c)
+add_library(read SHARED $ENV{BOLOS_SDK}/lib_standard_app/read.c)
+add_library(write SHARED $ENV{BOLOS_SDK}/lib_standard_app/write.c)
+add_library(format SHARED $ENV{BOLOS_SDK}/lib_standard_app/format.c)
+add_library(varint SHARED $ENV{BOLOS_SDK}/lib_standard_app/varint.c)
+add_library(apdu_parser SHARED $ENV{BOLOS_SDK}/lib_standard_app/parser.c)
add_library(transaction_deserialise ../../src/transaction/deserialise.c)
-add_library(transaction_utils ../../src/transaction/utils.c)
-add_library(transaction_types_multi_signature_registration ../../src/transaction/types/multi_signature_registration.c)
+add_library(transaction_utils ../../src/transaction/transaction_utils.c ../../src/ui/ui_utils.c)
add_library(transaction_types_ipfs ../../src/transaction/types/ipfs.c)
add_library(transaction_types_transfer ../../src/transaction/types/transfer.c)
-add_library(transaction_types_htlc_lock ../../src/transaction/types/htlc_lock.c)
-add_library(transaction_types_htlc_refund ../../src/transaction/types/htlc_refund.c)
-add_library(transaction_types_htlc_claim ../../src/transaction/types/htlc_claim.c)
add_library(transaction_types_burn ../../src/transaction/types/burn.c)
add_library(transaction_types_vote ../../src/transaction/types/vote.c)
+target_link_libraries(transaction_utils PUBLIC cmocka gcov format nano_char_table)
-target_link_libraries(test_base58 PUBLIC cmocka gcov base58)
-target_link_libraries(test_bip32 PUBLIC cmocka gcov bip32 read)
-target_link_libraries(test_buffer PUBLIC cmocka gcov buffer bip32 varint write read)
-target_link_libraries(test_format PUBLIC cmocka gcov format nano_char_table)
-target_link_libraries(test_write PUBLIC cmocka gcov write)
-target_link_libraries(test_apdu_parser PUBLIC cmocka gcov apdu_parser)
target_link_libraries(test_tx_parser PUBLIC
transaction_deserialise
buffer
@@ -85,25 +76,15 @@ target_link_libraries(test_tx_parser PUBLIC
gcov
write
read
- transaction_types_burn
- transaction_types_htlc_claim
- transaction_types_htlc_lock
- transaction_types_htlc_refund
transaction_types_ipfs
- transaction_types_multi_signature_registration
transaction_types_transfer
transaction_types_vote
+ transaction_types_burn
transaction_utils)
target_link_libraries(test_tx_utils PUBLIC
cmocka
gcov
transaction_utils)
-add_test(test_base58 test_base58)
-add_test(test_bip32 test_bip32)
-add_test(test_buffer test_buffer)
-add_test(test_format test_format)
-add_test(test_write test_write)
-add_test(test_apdu_parser test_apdu_parser)
add_test(test_tx_parser test_tx_parser)
add_test(test_tx_utils test_tx_utils)
diff --git a/tests/unit-tests/README.md b/tests/unit-tests/README.md
index ef41ce48..f41d4dd2 100644
--- a/tests/unit-tests/README.md
+++ b/tests/unit-tests/README.md
@@ -27,7 +27,7 @@ CTEST_OUTPUT_ON_FAILURE=1 make -C build test
## Generate code coverage
-Just execute in `tests/unit-tests` folder
+Just execute in `unit-tests` folder
```
./gen_coverage.sh
diff --git a/tests/unit-tests/test_apdu_parser.c b/tests/unit-tests/test_apdu_parser.c
deleted file mode 100644
index 555ede41..00000000
--- a/tests/unit-tests/test_apdu_parser.c
+++ /dev/null
@@ -1,41 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-#include "types.h"
-#include "apdu/parser.h"
-
-static void test_apdu_parser(void **state) {
- (void) state;
- uint8_t apdu_bad_min_len[] = {0xE0, 0xB2, 0x00, 0x00}; // less than 5 bytes
- uint8_t apdu_bad_lc[] = {0xE0, 0xB2, 0x00, 0x00, 0x01}; // Lc = 1 but no data
- uint8_t apdu[] = {0xE0, 0xB2, 0x01, 0x02, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04};
-
- command_t cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- assert_false(apdu_parser(&cmd, apdu_bad_min_len, sizeof(apdu_bad_min_len)));
-
- memset(&cmd, 0, sizeof(cmd));
- assert_false(apdu_parser(&cmd, apdu_bad_lc, sizeof(apdu_bad_min_len)));
-
- memset(&cmd, 0, sizeof(cmd));
- assert_true(apdu_parser(&cmd, apdu, sizeof(apdu)));
- assert_int_equal(cmd.cla, 0xE0);
- assert_int_equal(cmd.ins, 0xB2);
- assert_int_equal(cmd.p1, 0x01);
- assert_int_equal(cmd.p2, 0x02);
- assert_int_equal(cmd.lc, 5);
- assert_memory_equal(cmd.data, ((uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04}), cmd.lc);
-}
-
-int main() {
- const struct CMUnitTest tests[] = {cmocka_unit_test(test_apdu_parser)};
-
- return cmocka_run_group_tests(tests, NULL, NULL);
-}
diff --git a/tests/unit-tests/test_base58.c b/tests/unit-tests/test_base58.c
deleted file mode 100644
index f7f5e457..00000000
--- a/tests/unit-tests/test_base58.c
+++ /dev/null
@@ -1,34 +0,0 @@
-#include
-#include
-#include
-#include