diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 711779d18..a141a2d83 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -15,7 +15,7 @@ Describe your issue in as much detail as possible here. * OS and version * branch that causes this issue -* Device (Nano S, Nano X, Ledger Blue) +* Device (Nano S, Nano S Plus, Nano X, Ledger Blue) ## Steps to reproduce diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index f8abc5224..031ba337d 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -15,4 +15,4 @@ Describe your issue in as much detail as possible here. * OS and version * branch that causes this issue -* Device (Nano S, Nano X, Ledger Blue) \ No newline at end of file +* Device (Nano S, Nano S Plus, Nano X, Ledger Blue) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 3e15b7913..d5cf7959e 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -128,6 +128,7 @@ jobs: jobs-e2e-speculos-tests: name: Speculos tests strategy: + fail-fast: false matrix: model: ["nanosp", "nanos", "nanox"] @@ -153,7 +154,7 @@ jobs: run: | cd tests/speculos sudo apt-get update && sudo apt-get install -y qemu-user-static - pip install --extra-index-url https://test.pypi.org/simple/ -r requirements.txt + pip install -r requirements.txt - name: Run speculos tests run: | @@ -171,7 +172,6 @@ jobs: with: upload_app_binaries_artifact: "ragger_elfs" flags: "DEBUG=1 CAL_CI_KEY=1 DOMAIN_NAME_TEST_KEY=1" - run_for_devices: '["nanos", "nanox", "nanosp"]' jobs-ragger-tests: name: Run Ragger tests @@ -180,4 +180,3 @@ jobs: with: download_app_binaries_artifact: "ragger_elfs" test_dir: tests/ragger - run_for_devices: '["nanos", "nanox", "nanosp"]' diff --git a/.github/workflows/swap-ci-workflow.yml b/.github/workflows/swap-ci-workflow.yml new file mode 100644 index 000000000..3999224cf --- /dev/null +++ b/.github/workflows/swap-ci-workflow.yml @@ -0,0 +1,16 @@ +name: Swap functional tests + +on: + workflow_dispatch: + push: + branches: + - master + - develop + pull_request: + +jobs: + job_functional_tests: + uses: LedgerHQ/app-exchange/.github/workflows/reusable_swap_functional_tests.yml@develop + with: + branch_for_ethereum: ${{ github.ref }} + test_filter: '"ETH or eth or Ethereum or ethereum"' diff --git a/.gitignore b/.gitignore index 9443644b5..6779287da 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ bin/ debug/ dep/ obj/ +build/ # Python *.pyc diff --git a/CHANGELOG.md b/CHANGELOG.md index 50c74f734..6cd99025a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,33 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [1.10.3](https://github.com/ledgerhq/app-ethereum/compare/1.10.2...1.10.3) - 2023-07-27 + +### Added + +- (network) LUKSO mainnet & testnet +- (network) Chiado +- (network) PulseChain +- (network) Neon EVM mainnet & devnet +- (network) Venidium +- (network) Telos EVM mainnet +- (network) OKBChain mainnet +- (network) Polygon zkEVM +- (network) Base +- (network) Sepolia +- ENS on chains that share the Ethereum derivation path +- Ledger Stax support + +### Changed + +- (network) xDai renamed to Gnosis + +### Fixed + +- Missing context cleanup between plugin calls +- Miscellaneous swap issues +- Improper EIP-712 array handling + ## [1.10.2](https://github.com/ledgerhq/app-ethereum/compare/1.10.1...1.10.2) - 2023-04-24 ### Added diff --git a/Makefile b/Makefile index b7704d763..4715da52a 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ APP_LOAD_PARAMS += --path "1517992542'/1101353413'" APPVERSION_M=1 APPVERSION_N=10 -APPVERSION_P=2 +APPVERSION_P=3 APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) APP_LOAD_FLAGS= --appFlags 0xa40 --dep Ethereum:$(APPVERSION) @@ -54,6 +54,7 @@ include ./makefile_conf/chain/$(CHAIN).mk else $(error Unsupported CHAIN - use $(SUPPORTED_CHAINS)) endif +CFLAGS += -DAPPNAME=\"$(APPNAME)\" ######### # Other # @@ -65,6 +66,12 @@ DEFINES += $(DEFINES_LIB) #prepare hsm generation ifeq ($(TARGET_NAME),TARGET_NANOS) ICONNAME=icons/nanos_app_$(CHAIN).gif +else ifeq ($(TARGET_NAME),TARGET_STAX) +ICONNAME=icons/stax_app_$(CHAIN).gif +DEFINES += ICONGLYPH=C_stax_$(CHAIN)_64px +DEFINES += ICONBITMAP=C_stax_$(CHAIN)_64px_bitmap +DEFINES += ICONGLYPH_SMALL=C_stax_$(CHAIN) +GLYPH_FILES += $(ICONNAME) else ICONNAME=icons/nanox_app_$(CHAIN).gif endif @@ -79,9 +86,10 @@ all: default ############ DEFINES += OS_IO_SEPROXYHAL -DEFINES += HAVE_BAGL HAVE_SPRINTF HAVE_SNPRINTF_FORMAT_U +DEFINES += HAVE_SPRINTF HAVE_SNPRINTF_FORMAT_U DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=4 IO_HID_EP_LENGTH=64 HAVE_USB_APDU DEFINES += LEDGER_MAJOR_VERSION=$(APPVERSION_M) LEDGER_MINOR_VERSION=$(APPVERSION_N) LEDGER_PATCH_VERSION=$(APPVERSION_P) +DEFINES += BUILD_YEAR=\"$(shell date +%Y)\" # U2F DEFINES += HAVE_U2F HAVE_IO_U2F @@ -90,30 +98,41 @@ DEFINES += USB_SEGMENT_SIZE=64 DEFINES += BLE_SEGMENT_SIZE=32 #max MTU, min 20 DEFINES += UNUSED\(x\)=\(void\)x DEFINES += APPVERSION=\"$(APPVERSION)\" -DEFINES += HAVE_UX_FLOW #WEBUSB_URL = www.ledgerwallet.com #DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=$(shell echo -n $(WEBUSB_URL) | wc -c) WEBUSB_URL=$(shell echo -n $(WEBUSB_URL) | sed -e "s/./\\\'\0\\\',/g") DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=0 WEBUSB_URL="" -ifeq ($(TARGET_NAME),TARGET_NANOX) +ifneq (,$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX)) DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000 DEFINES += HAVE_BLE_APDU # basic ledger apdu transport over BLE +SDK_SOURCE_PATH += lib_blewbxx lib_blewbxx_impl endif ifeq ($(TARGET_NAME),TARGET_NANOS) -DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=72 -DEFINES += HAVE_WALLET_ID_SDK +DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 else DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300 +endif + +ifeq ($(TARGET_NAME),TARGET_STAX) +DEFINES += NBGL_QRCODE +else +DEFINES += HAVE_BAGL +DEFINES += HAVE_UX_FLOW +ifeq ($(TARGET_NAME),TARGET_NANOS) +DEFINES += HAVE_WALLET_ID_SDK +DEFINES += BAGL_WIDTH=128 BAGL_HEIGHT=32 +else DEFINES += HAVE_GLO096 -DEFINES += HAVE_BAGL BAGL_WIDTH=128 BAGL_HEIGHT=64 +DEFINES += BAGL_WIDTH=128 BAGL_HEIGHT=64 DEFINES += HAVE_BAGL_ELLIPSIS # long label truncation feature 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 +endif # Enables direct data signing without having to specify it in the settings. Useful when testing with speculos. ALLOW_DATA:=0 @@ -167,7 +186,6 @@ endif endif # Enabling debug PRINTF -DEBUG:=0 ifneq ($(DEBUG),0) DEFINES += HAVE_STACK_OVERFLOW_CHECK ifeq ($(TARGET_NAME),TARGET_NANOS) @@ -204,13 +222,11 @@ endif CC := $(CLANGPATH)clang -#CFLAGS += -O0 -CFLAGS += -Oz -Wno-format-invalid-specifier -Wno-format-extra-args +CFLAGS += -Wno-format-invalid-specifier -Wno-format-extra-args AS := $(GCCPATH)arm-none-eabi-gcc LD := $(GCCPATH)arm-none-eabi-gcc -LDFLAGS += -O3 -Os LDLIBS += -lm -lgcc -lc # import rules to compile glyphs(/pone) @@ -219,11 +235,12 @@ include $(BOLOS_SDK)/Makefile.glyphs ### variables processed by the common makefile.rules of the SDK to grab source files and include dirs APP_SOURCE_PATH += src_common src src_features src_plugins SDK_SOURCE_PATH += lib_stusb lib_stusb_impl lib_u2f +ifeq ($(TARGET_NAME),TARGET_STAX) +APP_SOURCE_PATH += src_nbgl +else SDK_SOURCE_PATH += lib_ux -ifeq ($(TARGET_NAME),TARGET_NANOX) -SDK_SOURCE_PATH += lib_blewbxx lib_blewbxx_impl -endif APP_SOURCE_PATH += src_bagl +endif ### initialize plugin SDK submodule if needed, rebuild it, and warn if a difference is noticed ifeq ($(CHAIN),ethereum) diff --git a/README.md b/README.md index 789a604aa..0293c3194 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@

app-ethereum

- Ethereum wallet application for Ledger Blue, Nano S and Nano X + Ethereum wallet application for Ledger Blue, Nano S, Nano S Plus and Nano X
« Explore the docs »
@@ -42,7 +42,7 @@ ## About the project -Ethereum wallet application framework for Nano S and Nano X. +Ethereum wallet application framework for Nano S, Nano S Plus and Nano X. Ledger Blue is not maintained anymore, but the app can still be compiled for this target using the branch [`blue-final-release`](https://github.com/LedgerHQ/app-ethereum/tree/blue-final-release). ## Documentation diff --git a/ethereum-plugin-sdk b/ethereum-plugin-sdk index a4b971f67..b9777e7a8 160000 --- a/ethereum-plugin-sdk +++ b/ethereum-plugin-sdk @@ -1 +1 @@ -Subproject commit a4b971f67980694d8c3862e793859209bc525545 +Subproject commit b9777e7a81a9c33b3f8997ffa23396fa2b3f861d diff --git a/glyphs/badge_transaction.gif b/glyphs/badge_transaction.gif deleted file mode 100644 index 131325d4a..000000000 Binary files a/glyphs/badge_transaction.gif and /dev/null differ diff --git a/glyphs/blue_badge_akroma.gif b/glyphs/blue_badge_akroma.gif deleted file mode 100644 index 40b3320c4..000000000 Binary files a/glyphs/blue_badge_akroma.gif and /dev/null differ diff --git a/glyphs/blue_badge_atheios.gif b/glyphs/blue_badge_atheios.gif deleted file mode 100644 index 5174214f3..000000000 Binary files a/glyphs/blue_badge_atheios.gif and /dev/null differ diff --git a/glyphs/blue_badge_callisto.gif b/glyphs/blue_badge_callisto.gif deleted file mode 100644 index 43a8c3563..000000000 Binary files a/glyphs/blue_badge_callisto.gif and /dev/null differ diff --git a/glyphs/blue_badge_dexon.gif b/glyphs/blue_badge_dexon.gif deleted file mode 100644 index 9b4dd9e7c..000000000 Binary files a/glyphs/blue_badge_dexon.gif and /dev/null differ diff --git a/glyphs/blue_badge_ellaism.gif b/glyphs/blue_badge_ellaism.gif deleted file mode 100644 index cb4d811e4..000000000 Binary files a/glyphs/blue_badge_ellaism.gif and /dev/null differ diff --git a/glyphs/blue_badge_eosclassic.gif b/glyphs/blue_badge_eosclassic.gif deleted file mode 100644 index 3ad0bbaad..000000000 Binary files a/glyphs/blue_badge_eosclassic.gif and /dev/null differ diff --git a/glyphs/blue_badge_ether1.gif b/glyphs/blue_badge_ether1.gif deleted file mode 100644 index 5174214f3..000000000 Binary files a/glyphs/blue_badge_ether1.gif and /dev/null differ diff --git a/glyphs/blue_badge_ethereum.gif b/glyphs/blue_badge_ethereum.gif deleted file mode 100644 index 5174214f3..000000000 Binary files a/glyphs/blue_badge_ethereum.gif and /dev/null differ diff --git a/glyphs/blue_badge_ethereum_classic.gif b/glyphs/blue_badge_ethereum_classic.gif deleted file mode 100644 index 5174214f3..000000000 Binary files a/glyphs/blue_badge_ethereum_classic.gif and /dev/null differ diff --git a/glyphs/blue_badge_ethergem.gif b/glyphs/blue_badge_ethergem.gif deleted file mode 100644 index 01676ade0..000000000 Binary files a/glyphs/blue_badge_ethergem.gif and /dev/null differ diff --git a/glyphs/blue_badge_ethersocial.gif b/glyphs/blue_badge_ethersocial.gif deleted file mode 100644 index 011545f63..000000000 Binary files a/glyphs/blue_badge_ethersocial.gif and /dev/null differ diff --git a/glyphs/blue_badge_expanse.gif b/glyphs/blue_badge_expanse.gif deleted file mode 100644 index 9de8e125c..000000000 Binary files a/glyphs/blue_badge_expanse.gif and /dev/null differ diff --git a/glyphs/blue_badge_gochain.gif b/glyphs/blue_badge_gochain.gif deleted file mode 100644 index 4a8ea11eb..000000000 Binary files a/glyphs/blue_badge_gochain.gif and /dev/null differ diff --git a/glyphs/blue_badge_hpb.gif b/glyphs/blue_badge_hpb.gif deleted file mode 100644 index 3b64b0c2a..000000000 Binary files a/glyphs/blue_badge_hpb.gif and /dev/null differ diff --git a/glyphs/blue_badge_mix.gif b/glyphs/blue_badge_mix.gif deleted file mode 100644 index 5174214f3..000000000 Binary files a/glyphs/blue_badge_mix.gif and /dev/null differ diff --git a/glyphs/blue_badge_musicoin.gif b/glyphs/blue_badge_musicoin.gif deleted file mode 100644 index c56081dfc..000000000 Binary files a/glyphs/blue_badge_musicoin.gif and /dev/null differ diff --git a/glyphs/blue_badge_pirl.gif b/glyphs/blue_badge_pirl.gif deleted file mode 100644 index 19a25f9ff..000000000 Binary files a/glyphs/blue_badge_pirl.gif and /dev/null differ diff --git a/glyphs/blue_badge_poa.gif b/glyphs/blue_badge_poa.gif deleted file mode 100644 index 62d6c065b..000000000 Binary files a/glyphs/blue_badge_poa.gif and /dev/null differ diff --git a/glyphs/blue_badge_reosc.gif b/glyphs/blue_badge_reosc.gif deleted file mode 100644 index 5174214f3..000000000 Binary files a/glyphs/blue_badge_reosc.gif and /dev/null differ diff --git a/glyphs/blue_badge_ropsten.gif b/glyphs/blue_badge_ropsten.gif deleted file mode 100644 index 5174214f3..000000000 Binary files a/glyphs/blue_badge_ropsten.gif and /dev/null differ diff --git a/glyphs/blue_badge_rsk.gif b/glyphs/blue_badge_rsk.gif deleted file mode 100644 index 5174214f3..000000000 Binary files a/glyphs/blue_badge_rsk.gif and /dev/null differ diff --git a/glyphs/blue_badge_rsk_testnet.gif b/glyphs/blue_badge_rsk_testnet.gif deleted file mode 100644 index 5174214f3..000000000 Binary files a/glyphs/blue_badge_rsk_testnet.gif and /dev/null differ diff --git a/glyphs/blue_badge_thundercore.gif b/glyphs/blue_badge_thundercore.gif deleted file mode 100644 index a31bbe32d..000000000 Binary files a/glyphs/blue_badge_thundercore.gif and /dev/null differ diff --git a/glyphs/blue_badge_tomochain.gif b/glyphs/blue_badge_tomochain.gif deleted file mode 100644 index 624837f5a..000000000 Binary files a/glyphs/blue_badge_tomochain.gif and /dev/null differ diff --git a/glyphs/blue_badge_ubiq.gif b/glyphs/blue_badge_ubiq.gif deleted file mode 100644 index 69b1cf3ae..000000000 Binary files a/glyphs/blue_badge_ubiq.gif and /dev/null differ diff --git a/glyphs/blue_badge_wanchain.gif b/glyphs/blue_badge_wanchain.gif deleted file mode 100644 index deb64841e..000000000 Binary files a/glyphs/blue_badge_wanchain.gif and /dev/null differ diff --git a/glyphs/blue_badge_webchain.gif b/glyphs/blue_badge_webchain.gif deleted file mode 100644 index 24edd1c2a..000000000 Binary files a/glyphs/blue_badge_webchain.gif and /dev/null differ diff --git a/glyphs/icon_back.gif b/glyphs/icon_back.gif deleted file mode 100644 index a2a7e6d4f..000000000 Binary files a/glyphs/icon_back.gif and /dev/null differ diff --git a/glyphs/icon_back_x.gif b/glyphs/icon_back_x.gif deleted file mode 100644 index ff043615c..000000000 Binary files a/glyphs/icon_back_x.gif and /dev/null differ diff --git a/glyphs/icon_certificate.gif b/glyphs/icon_certificate.gif deleted file mode 100644 index 89b529f79..000000000 Binary files a/glyphs/icon_certificate.gif and /dev/null differ diff --git a/glyphs/icon_crossmark.gif b/glyphs/icon_crossmark.gif deleted file mode 100644 index 2dcf9d9ee..000000000 Binary files a/glyphs/icon_crossmark.gif and /dev/null differ diff --git a/glyphs/icon_dashboard.gif b/glyphs/icon_dashboard.gif deleted file mode 100644 index 5c305517f..000000000 Binary files a/glyphs/icon_dashboard.gif and /dev/null differ diff --git a/glyphs/icon_dashboard_x.gif b/glyphs/icon_dashboard_x.gif deleted file mode 100644 index 33d9b0a74..000000000 Binary files a/glyphs/icon_dashboard_x.gif and /dev/null differ diff --git a/glyphs/icon_down.gif b/glyphs/icon_down.gif deleted file mode 100644 index 4f4e39ee3..000000000 Binary files a/glyphs/icon_down.gif and /dev/null differ diff --git a/glyphs/icon_eye.gif b/glyphs/icon_eye.gif deleted file mode 100644 index df4bb829e..000000000 Binary files a/glyphs/icon_eye.gif and /dev/null differ diff --git a/glyphs/icon_left.gif b/glyphs/icon_left.gif deleted file mode 100644 index 524226ba1..000000000 Binary files a/glyphs/icon_left.gif and /dev/null differ diff --git a/glyphs/icon_right.gif b/glyphs/icon_right.gif deleted file mode 100644 index 15ff3cf59..000000000 Binary files a/glyphs/icon_right.gif and /dev/null differ diff --git a/glyphs/icon_toggle_reset.gif b/glyphs/icon_toggle_reset.gif deleted file mode 100644 index 450bc869d..000000000 Binary files a/glyphs/icon_toggle_reset.gif and /dev/null differ diff --git a/glyphs/icon_toggle_set.gif b/glyphs/icon_toggle_set.gif deleted file mode 100644 index 571264c79..000000000 Binary files a/glyphs/icon_toggle_set.gif and /dev/null differ diff --git a/glyphs/icon_up.gif b/glyphs/icon_up.gif deleted file mode 100644 index 4e13c064f..000000000 Binary files a/glyphs/icon_up.gif and /dev/null differ diff --git a/glyphs/icon_validate_14.gif b/glyphs/icon_validate_14.gif deleted file mode 100644 index ccb5cabe3..000000000 Binary files a/glyphs/icon_validate_14.gif and /dev/null differ diff --git a/glyphs/icon_warning.gif b/glyphs/icon_warning.gif deleted file mode 100644 index 08bd4a739..000000000 Binary files a/glyphs/icon_warning.gif and /dev/null differ diff --git a/glyphs/nanos_badge_akroma.gif b/glyphs/nanos_badge_akroma.gif deleted file mode 100644 index 9dfdea6ed..000000000 Binary files a/glyphs/nanos_badge_akroma.gif and /dev/null differ diff --git a/glyphs/nanos_badge_artis_sigma1.gif b/glyphs/nanos_badge_artis_sigma1.gif deleted file mode 100644 index 3ef0eaa6f..000000000 Binary files a/glyphs/nanos_badge_artis_sigma1.gif and /dev/null differ diff --git a/glyphs/nanos_badge_artis_tau1.gif b/glyphs/nanos_badge_artis_tau1.gif deleted file mode 100644 index 9e741b54e..000000000 Binary files a/glyphs/nanos_badge_artis_tau1.gif and /dev/null differ diff --git a/glyphs/nanos_badge_atheios.gif b/glyphs/nanos_badge_atheios.gif deleted file mode 100644 index e7447fadc..000000000 Binary files a/glyphs/nanos_badge_atheios.gif and /dev/null differ diff --git a/glyphs/nanos_badge_callisto.gif b/glyphs/nanos_badge_callisto.gif deleted file mode 100644 index 25a0cddfe..000000000 Binary files a/glyphs/nanos_badge_callisto.gif and /dev/null differ diff --git a/glyphs/nanos_badge_dexon.gif b/glyphs/nanos_badge_dexon.gif deleted file mode 100644 index 65021cc8c..000000000 Binary files a/glyphs/nanos_badge_dexon.gif and /dev/null differ diff --git a/glyphs/nanos_badge_ellaism.gif b/glyphs/nanos_badge_ellaism.gif deleted file mode 100644 index d07bad78f..000000000 Binary files a/glyphs/nanos_badge_ellaism.gif and /dev/null differ diff --git a/glyphs/nanos_badge_ether1.gif b/glyphs/nanos_badge_ether1.gif deleted file mode 100644 index 776f6454b..000000000 Binary files a/glyphs/nanos_badge_ether1.gif and /dev/null differ diff --git a/glyphs/nanos_badge_ethereum.gif b/glyphs/nanos_badge_ethereum.gif deleted file mode 100644 index 776f6454b..000000000 Binary files a/glyphs/nanos_badge_ethereum.gif and /dev/null differ diff --git a/glyphs/nanos_badge_ethereum_classic.gif b/glyphs/nanos_badge_ethereum_classic.gif deleted file mode 100644 index 776f6454b..000000000 Binary files a/glyphs/nanos_badge_ethereum_classic.gif and /dev/null differ diff --git a/glyphs/nanos_badge_ethergem.gif b/glyphs/nanos_badge_ethergem.gif deleted file mode 100644 index 19b762159..000000000 Binary files a/glyphs/nanos_badge_ethergem.gif and /dev/null differ diff --git a/glyphs/nanos_badge_ethersocial.gif b/glyphs/nanos_badge_ethersocial.gif deleted file mode 100644 index 21262eba8..000000000 Binary files a/glyphs/nanos_badge_ethersocial.gif and /dev/null differ diff --git a/glyphs/nanos_badge_expanse.gif b/glyphs/nanos_badge_expanse.gif deleted file mode 100644 index b1c996dba..000000000 Binary files a/glyphs/nanos_badge_expanse.gif and /dev/null differ diff --git a/glyphs/nanos_badge_gochain.gif b/glyphs/nanos_badge_gochain.gif deleted file mode 100644 index 39ed2fb3f..000000000 Binary files a/glyphs/nanos_badge_gochain.gif and /dev/null differ diff --git a/glyphs/nanos_badge_hpb.gif b/glyphs/nanos_badge_hpb.gif deleted file mode 100644 index ee2a1f0c8..000000000 Binary files a/glyphs/nanos_badge_hpb.gif and /dev/null differ diff --git a/glyphs/nanos_badge_kusd.gif b/glyphs/nanos_badge_kusd.gif deleted file mode 100644 index b1ac932b7..000000000 Binary files a/glyphs/nanos_badge_kusd.gif and /dev/null differ diff --git a/glyphs/nanos_badge_mix.gif b/glyphs/nanos_badge_mix.gif deleted file mode 100644 index 776f6454b..000000000 Binary files a/glyphs/nanos_badge_mix.gif and /dev/null differ diff --git a/glyphs/nanos_badge_musicoin.gif b/glyphs/nanos_badge_musicoin.gif deleted file mode 100644 index b8288acd0..000000000 Binary files a/glyphs/nanos_badge_musicoin.gif and /dev/null differ diff --git a/glyphs/nanos_badge_pirl.gif b/glyphs/nanos_badge_pirl.gif deleted file mode 100644 index ab21513c4..000000000 Binary files a/glyphs/nanos_badge_pirl.gif and /dev/null differ diff --git a/glyphs/nanos_badge_poa.gif b/glyphs/nanos_badge_poa.gif deleted file mode 100644 index e45186609..000000000 Binary files a/glyphs/nanos_badge_poa.gif and /dev/null differ diff --git a/glyphs/nanos_badge_reosc.gif b/glyphs/nanos_badge_reosc.gif deleted file mode 100644 index fe388baea..000000000 Binary files a/glyphs/nanos_badge_reosc.gif and /dev/null differ diff --git a/glyphs/nanos_badge_ropsten.gif b/glyphs/nanos_badge_ropsten.gif deleted file mode 100644 index 776f6454b..000000000 Binary files a/glyphs/nanos_badge_ropsten.gif and /dev/null differ diff --git a/glyphs/nanos_badge_rsk.gif b/glyphs/nanos_badge_rsk.gif deleted file mode 100644 index 5ca99a56e..000000000 Binary files a/glyphs/nanos_badge_rsk.gif and /dev/null differ diff --git a/glyphs/nanos_badge_rsk_testnet.gif b/glyphs/nanos_badge_rsk_testnet.gif deleted file mode 100644 index 776f6454b..000000000 Binary files a/glyphs/nanos_badge_rsk_testnet.gif and /dev/null differ diff --git a/glyphs/nanos_badge_thundercore.gif b/glyphs/nanos_badge_thundercore.gif deleted file mode 100644 index e72367907..000000000 Binary files a/glyphs/nanos_badge_thundercore.gif and /dev/null differ diff --git a/glyphs/nanos_badge_tomochain.gif b/glyphs/nanos_badge_tomochain.gif deleted file mode 100644 index f33c2ba01..000000000 Binary files a/glyphs/nanos_badge_tomochain.gif and /dev/null differ diff --git a/glyphs/nanos_badge_ubiq.gif b/glyphs/nanos_badge_ubiq.gif deleted file mode 100644 index d2ce45c40..000000000 Binary files a/glyphs/nanos_badge_ubiq.gif and /dev/null differ diff --git a/glyphs/nanos_badge_wanchain.gif b/glyphs/nanos_badge_wanchain.gif deleted file mode 100644 index 53bdccdde..000000000 Binary files a/glyphs/nanos_badge_wanchain.gif and /dev/null differ diff --git a/glyphs/nanos_badge_webchain.gif b/glyphs/nanos_badge_webchain.gif deleted file mode 100644 index 515eed39f..000000000 Binary files a/glyphs/nanos_badge_webchain.gif and /dev/null differ diff --git a/glyphs/stax_akroma_64px.gif b/glyphs/stax_akroma_64px.gif new file mode 100644 index 000000000..d092851df Binary files /dev/null and b/glyphs/stax_akroma_64px.gif differ diff --git a/glyphs/stax_apothemnetwork_64px.gif b/glyphs/stax_apothemnetwork_64px.gif new file mode 100644 index 000000000..974f8bb31 Binary files /dev/null and b/glyphs/stax_apothemnetwork_64px.gif differ diff --git a/glyphs/stax_artis_sigma1_64px.gif b/glyphs/stax_artis_sigma1_64px.gif new file mode 100644 index 000000000..05c4f221c Binary files /dev/null and b/glyphs/stax_artis_sigma1_64px.gif differ diff --git a/glyphs/stax_artis_tau1_64px.gif b/glyphs/stax_artis_tau1_64px.gif new file mode 100644 index 000000000..87b527dae Binary files /dev/null and b/glyphs/stax_artis_tau1_64px.gif differ diff --git a/glyphs/stax_astar_64px.gif b/glyphs/stax_astar_64px.gif new file mode 100644 index 000000000..60fb1e8fc Binary files /dev/null and b/glyphs/stax_astar_64px.gif differ diff --git a/glyphs/stax_atheios_64px.gif b/glyphs/stax_atheios_64px.gif new file mode 100644 index 000000000..051e9c37e Binary files /dev/null and b/glyphs/stax_atheios_64px.gif differ diff --git a/glyphs/stax_bsc_64px.gif b/glyphs/stax_bsc_64px.gif new file mode 100644 index 000000000..956f73dcc Binary files /dev/null and b/glyphs/stax_bsc_64px.gif differ diff --git a/glyphs/stax_bttc_64px.gif b/glyphs/stax_bttc_64px.gif new file mode 100644 index 000000000..99e51ff01 Binary files /dev/null and b/glyphs/stax_bttc_64px.gif differ diff --git a/glyphs/stax_callisto_64px.gif b/glyphs/stax_callisto_64px.gif new file mode 100644 index 000000000..44a6b888a Binary files /dev/null and b/glyphs/stax_callisto_64px.gif differ diff --git a/glyphs/stax_conflux_espace_64px.gif b/glyphs/stax_conflux_espace_64px.gif new file mode 100644 index 000000000..d6f790d41 Binary files /dev/null and b/glyphs/stax_conflux_espace_64px.gif differ diff --git a/glyphs/stax_cube_64px.gif b/glyphs/stax_cube_64px.gif new file mode 100644 index 000000000..818672285 Binary files /dev/null and b/glyphs/stax_cube_64px.gif differ diff --git a/glyphs/stax_dexon_64px.gif b/glyphs/stax_dexon_64px.gif new file mode 100644 index 000000000..d37f6b26b Binary files /dev/null and b/glyphs/stax_dexon_64px.gif differ diff --git a/glyphs/stax_ellaism_64px.gif b/glyphs/stax_ellaism_64px.gif new file mode 100644 index 000000000..b785d4899 Binary files /dev/null and b/glyphs/stax_ellaism_64px.gif differ diff --git a/glyphs/stax_energywebchain_64px.gif b/glyphs/stax_energywebchain_64px.gif new file mode 100644 index 000000000..5cd4c4da1 Binary files /dev/null and b/glyphs/stax_energywebchain_64px.gif differ diff --git a/glyphs/stax_ether1_64px.gif b/glyphs/stax_ether1_64px.gif new file mode 100644 index 000000000..ec41146ed Binary files /dev/null and b/glyphs/stax_ether1_64px.gif differ diff --git a/glyphs/stax_ethereum_64px.gif b/glyphs/stax_ethereum_64px.gif new file mode 100644 index 000000000..7cd7be3df Binary files /dev/null and b/glyphs/stax_ethereum_64px.gif differ diff --git a/glyphs/stax_ethereum_classic_64px.gif b/glyphs/stax_ethereum_classic_64px.gif new file mode 100644 index 000000000..5aeed55c1 Binary files /dev/null and b/glyphs/stax_ethereum_classic_64px.gif differ diff --git a/glyphs/stax_ethergem_64px.gif b/glyphs/stax_ethergem_64px.gif new file mode 100644 index 000000000..8bdb8e5f1 Binary files /dev/null and b/glyphs/stax_ethergem_64px.gif differ diff --git a/glyphs/stax_ethersocial_64px.gif b/glyphs/stax_ethersocial_64px.gif new file mode 100644 index 000000000..530fe5540 Binary files /dev/null and b/glyphs/stax_ethersocial_64px.gif differ diff --git a/glyphs/stax_expanse_64px.gif b/glyphs/stax_expanse_64px.gif new file mode 100644 index 000000000..61698c8d9 Binary files /dev/null and b/glyphs/stax_expanse_64px.gif differ diff --git a/glyphs/stax_flare_64px.gif b/glyphs/stax_flare_64px.gif new file mode 100644 index 000000000..c834fcb36 Binary files /dev/null and b/glyphs/stax_flare_64px.gif differ diff --git a/glyphs/stax_flare_coston_64px.gif b/glyphs/stax_flare_coston_64px.gif new file mode 100644 index 000000000..28822f300 Binary files /dev/null and b/glyphs/stax_flare_coston_64px.gif differ diff --git a/glyphs/stax_gochain_64px.gif b/glyphs/stax_gochain_64px.gif new file mode 100644 index 000000000..aec56d005 Binary files /dev/null and b/glyphs/stax_gochain_64px.gif differ diff --git a/glyphs/stax_goerli_64px.gif b/glyphs/stax_goerli_64px.gif new file mode 100644 index 000000000..3c4839434 Binary files /dev/null and b/glyphs/stax_goerli_64px.gif differ diff --git a/glyphs/stax_hpb_64px.gif b/glyphs/stax_hpb_64px.gif new file mode 100644 index 000000000..392151ae6 Binary files /dev/null and b/glyphs/stax_hpb_64px.gif differ diff --git a/glyphs/stax_id4good_64px.gif b/glyphs/stax_id4good_64px.gif new file mode 100644 index 000000000..6d04b228f Binary files /dev/null and b/glyphs/stax_id4good_64px.gif differ diff --git a/glyphs/stax_kardiachain_64px.gif b/glyphs/stax_kardiachain_64px.gif new file mode 100644 index 000000000..66b6e6fb9 Binary files /dev/null and b/glyphs/stax_kardiachain_64px.gif differ diff --git a/glyphs/stax_kusd_64px.gif b/glyphs/stax_kusd_64px.gif new file mode 100644 index 000000000..b18730662 Binary files /dev/null and b/glyphs/stax_kusd_64px.gif differ diff --git a/glyphs/stax_meter_64px.gif b/glyphs/stax_meter_64px.gif new file mode 100644 index 000000000..ee0804bc3 Binary files /dev/null and b/glyphs/stax_meter_64px.gif differ diff --git a/glyphs/stax_mix_64px.gif b/glyphs/stax_mix_64px.gif new file mode 100644 index 000000000..e3a3e570a Binary files /dev/null and b/glyphs/stax_mix_64px.gif differ diff --git a/glyphs/stax_moonbeam_64px.gif b/glyphs/stax_moonbeam_64px.gif new file mode 100644 index 000000000..e8485ee55 Binary files /dev/null and b/glyphs/stax_moonbeam_64px.gif differ diff --git a/glyphs/stax_moonriver_64px.gif b/glyphs/stax_moonriver_64px.gif new file mode 100644 index 000000000..180985709 Binary files /dev/null and b/glyphs/stax_moonriver_64px.gif differ diff --git a/glyphs/stax_multivac_64px.gif b/glyphs/stax_multivac_64px.gif new file mode 100644 index 000000000..e3ea71657 Binary files /dev/null and b/glyphs/stax_multivac_64px.gif differ diff --git a/glyphs/stax_musicoin_64px.gif b/glyphs/stax_musicoin_64px.gif new file mode 100644 index 000000000..d9dce6c3f Binary files /dev/null and b/glyphs/stax_musicoin_64px.gif differ diff --git a/glyphs/stax_oasys_64px.gif b/glyphs/stax_oasys_64px.gif new file mode 100644 index 000000000..81c0e5fe8 Binary files /dev/null and b/glyphs/stax_oasys_64px.gif differ diff --git a/glyphs/stax_okc_64px.gif b/glyphs/stax_okc_64px.gif new file mode 100644 index 000000000..f377521af Binary files /dev/null and b/glyphs/stax_okc_64px.gif differ diff --git a/glyphs/stax_pirl_64px.gif b/glyphs/stax_pirl_64px.gif new file mode 100644 index 000000000..7c9733164 Binary files /dev/null and b/glyphs/stax_pirl_64px.gif differ diff --git a/glyphs/stax_poa_64px.gif b/glyphs/stax_poa_64px.gif new file mode 100644 index 000000000..d857c1781 Binary files /dev/null and b/glyphs/stax_poa_64px.gif differ diff --git a/glyphs/stax_polygon_64px.gif b/glyphs/stax_polygon_64px.gif new file mode 100644 index 000000000..40b99e10b Binary files /dev/null and b/glyphs/stax_polygon_64px.gif differ diff --git a/glyphs/stax_reosc_64px.gif b/glyphs/stax_reosc_64px.gif new file mode 100644 index 000000000..fa727e370 Binary files /dev/null and b/glyphs/stax_reosc_64px.gif differ diff --git a/glyphs/stax_ropsten_64px.gif b/glyphs/stax_ropsten_64px.gif new file mode 100644 index 000000000..6025affd8 Binary files /dev/null and b/glyphs/stax_ropsten_64px.gif differ diff --git a/glyphs/stax_rsk_64px.gif b/glyphs/stax_rsk_64px.gif new file mode 100644 index 000000000..5e25ff6b2 Binary files /dev/null and b/glyphs/stax_rsk_64px.gif differ diff --git a/glyphs/stax_rsk_testnet_64px.gif b/glyphs/stax_rsk_testnet_64px.gif new file mode 100644 index 000000000..5e25ff6b2 Binary files /dev/null and b/glyphs/stax_rsk_testnet_64px.gif differ diff --git a/glyphs/stax_shiden_64px.gif b/glyphs/stax_shiden_64px.gif new file mode 100644 index 000000000..6bbe136ca Binary files /dev/null and b/glyphs/stax_shiden_64px.gif differ diff --git a/glyphs/stax_shyft_64px.gif b/glyphs/stax_shyft_64px.gif new file mode 100644 index 000000000..78a7ea9c8 Binary files /dev/null and b/glyphs/stax_shyft_64px.gif differ diff --git a/glyphs/stax_songbird_64px.gif b/glyphs/stax_songbird_64px.gif new file mode 100644 index 000000000..e635b9569 Binary files /dev/null and b/glyphs/stax_songbird_64px.gif differ diff --git a/glyphs/stax_tecracoin_64px.gif b/glyphs/stax_tecracoin_64px.gif new file mode 100644 index 000000000..4fa9b491c Binary files /dev/null and b/glyphs/stax_tecracoin_64px.gif differ diff --git a/glyphs/stax_tecratestnet_64px.gif b/glyphs/stax_tecratestnet_64px.gif new file mode 100644 index 000000000..4fa9b491c Binary files /dev/null and b/glyphs/stax_tecratestnet_64px.gif differ diff --git a/glyphs/stax_thundercore_64px.gif b/glyphs/stax_thundercore_64px.gif new file mode 100644 index 000000000..76134be81 Binary files /dev/null and b/glyphs/stax_thundercore_64px.gif differ diff --git a/glyphs/stax_tobalaba_64px.gif b/glyphs/stax_tobalaba_64px.gif new file mode 100644 index 000000000..0125e6b45 Binary files /dev/null and b/glyphs/stax_tobalaba_64px.gif differ diff --git a/glyphs/stax_tomochain_64px.gif b/glyphs/stax_tomochain_64px.gif new file mode 100644 index 000000000..6abef3351 Binary files /dev/null and b/glyphs/stax_tomochain_64px.gif differ diff --git a/glyphs/stax_ubiq_64px.gif b/glyphs/stax_ubiq_64px.gif new file mode 100644 index 000000000..740b7e99c Binary files /dev/null and b/glyphs/stax_ubiq_64px.gif differ diff --git a/glyphs/stax_volta_64px.gif b/glyphs/stax_volta_64px.gif new file mode 100644 index 000000000..83cfb91c4 Binary files /dev/null and b/glyphs/stax_volta_64px.gif differ diff --git a/glyphs/stax_wanchain_64px.gif b/glyphs/stax_wanchain_64px.gif new file mode 100644 index 000000000..27a5582da Binary files /dev/null and b/glyphs/stax_wanchain_64px.gif differ diff --git a/glyphs/stax_webchain_64px.gif b/glyphs/stax_webchain_64px.gif new file mode 100644 index 000000000..585832f1d Binary files /dev/null and b/glyphs/stax_webchain_64px.gif differ diff --git a/glyphs/stax_wethio_64px.gif b/glyphs/stax_wethio_64px.gif new file mode 100644 index 000000000..8a66b1209 Binary files /dev/null and b/glyphs/stax_wethio_64px.gif differ diff --git a/glyphs/stax_xdcnetwork_64px.gif b/glyphs/stax_xdcnetwork_64px.gif new file mode 100644 index 000000000..b990ab31e Binary files /dev/null and b/glyphs/stax_xdcnetwork_64px.gif differ diff --git a/icons/akroma.png b/icons/akroma.png deleted file mode 100644 index 22baa92a1..000000000 Binary files a/icons/akroma.png and /dev/null differ diff --git a/icons/artis_sigma1.png b/icons/artis_sigma1.png deleted file mode 100644 index f6b47b129..000000000 Binary files a/icons/artis_sigma1.png and /dev/null differ diff --git a/icons/artis_tau1.png b/icons/artis_tau1.png deleted file mode 100644 index 388009a32..000000000 Binary files a/icons/artis_tau1.png and /dev/null differ diff --git a/icons/atheios.png b/icons/atheios.png deleted file mode 100644 index 22af8d272..000000000 Binary files a/icons/atheios.png and /dev/null differ diff --git a/icons/blue_app_akroma.gif b/icons/blue_app_akroma.gif deleted file mode 100644 index 12c9cd215..000000000 Binary files a/icons/blue_app_akroma.gif and /dev/null differ diff --git a/icons/blue_app_artis_sigma1.gif b/icons/blue_app_artis_sigma1.gif deleted file mode 100644 index 8c47bf3a5..000000000 Binary files a/icons/blue_app_artis_sigma1.gif and /dev/null differ diff --git a/icons/blue_app_artis_tau1.gif b/icons/blue_app_artis_tau1.gif deleted file mode 100644 index 3dfdf0629..000000000 Binary files a/icons/blue_app_artis_tau1.gif and /dev/null differ diff --git a/icons/blue_app_atheios.gif b/icons/blue_app_atheios.gif deleted file mode 100644 index 916915645..000000000 Binary files a/icons/blue_app_atheios.gif and /dev/null differ diff --git a/icons/blue_app_callisto.gif b/icons/blue_app_callisto.gif deleted file mode 100644 index 162765a35..000000000 Binary files a/icons/blue_app_callisto.gif and /dev/null differ diff --git a/icons/blue_app_dexon.gif b/icons/blue_app_dexon.gif deleted file mode 100644 index 3f51c6bc5..000000000 Binary files a/icons/blue_app_dexon.gif and /dev/null differ diff --git a/icons/blue_app_ellaism.gif b/icons/blue_app_ellaism.gif deleted file mode 100644 index 0936f88ba..000000000 Binary files a/icons/blue_app_ellaism.gif and /dev/null differ diff --git a/icons/blue_app_ether1.gif b/icons/blue_app_ether1.gif deleted file mode 100644 index 1592686a1..000000000 Binary files a/icons/blue_app_ether1.gif and /dev/null differ diff --git a/icons/blue_app_ethereum.gif b/icons/blue_app_ethereum.gif deleted file mode 100644 index c3d5c4e1d..000000000 Binary files a/icons/blue_app_ethereum.gif and /dev/null differ diff --git a/icons/blue_app_ethereum_classic.gif b/icons/blue_app_ethereum_classic.gif deleted file mode 100644 index dceaa1510..000000000 Binary files a/icons/blue_app_ethereum_classic.gif and /dev/null differ diff --git a/icons/blue_app_ethergem.gif b/icons/blue_app_ethergem.gif deleted file mode 100644 index 539f76ebd..000000000 Binary files a/icons/blue_app_ethergem.gif and /dev/null differ diff --git a/icons/blue_app_ethersocial.gif b/icons/blue_app_ethersocial.gif deleted file mode 100644 index 2df10f438..000000000 Binary files a/icons/blue_app_ethersocial.gif and /dev/null differ diff --git a/icons/blue_app_ewc.gif b/icons/blue_app_ewc.gif deleted file mode 100644 index d1c438fce..000000000 Binary files a/icons/blue_app_ewc.gif and /dev/null differ diff --git a/icons/blue_app_expanse.gif b/icons/blue_app_expanse.gif deleted file mode 100644 index 82660042d..000000000 Binary files a/icons/blue_app_expanse.gif and /dev/null differ diff --git a/icons/blue_app_gochain.gif b/icons/blue_app_gochain.gif deleted file mode 100644 index 50ae2bee9..000000000 Binary files a/icons/blue_app_gochain.gif and /dev/null differ diff --git a/icons/blue_app_goerli.gif b/icons/blue_app_goerli.gif deleted file mode 100644 index c3d5c4e1d..000000000 Binary files a/icons/blue_app_goerli.gif and /dev/null differ diff --git a/icons/blue_app_hpb.gif b/icons/blue_app_hpb.gif deleted file mode 100644 index d15b589b0..000000000 Binary files a/icons/blue_app_hpb.gif and /dev/null differ diff --git a/icons/blue_app_kusd.gif b/icons/blue_app_kusd.gif deleted file mode 100644 index d4c5496a1..000000000 Binary files a/icons/blue_app_kusd.gif and /dev/null differ diff --git a/icons/blue_app_mix.gif b/icons/blue_app_mix.gif deleted file mode 100644 index 38cdca838..000000000 Binary files a/icons/blue_app_mix.gif and /dev/null differ diff --git a/icons/blue_app_musicoin.gif b/icons/blue_app_musicoin.gif deleted file mode 100644 index 42f818510..000000000 Binary files a/icons/blue_app_musicoin.gif and /dev/null differ diff --git a/icons/blue_app_pirl.gif b/icons/blue_app_pirl.gif deleted file mode 100644 index a6824ae7d..000000000 Binary files a/icons/blue_app_pirl.gif and /dev/null differ diff --git a/icons/blue_app_poa.gif b/icons/blue_app_poa.gif deleted file mode 100644 index 679fc6661..000000000 Binary files a/icons/blue_app_poa.gif and /dev/null differ diff --git a/icons/blue_app_reosc.gif b/icons/blue_app_reosc.gif deleted file mode 100644 index aaf46981d..000000000 Binary files a/icons/blue_app_reosc.gif and /dev/null differ diff --git a/icons/blue_app_ropsten.gif b/icons/blue_app_ropsten.gif deleted file mode 100644 index c3d5c4e1d..000000000 Binary files a/icons/blue_app_ropsten.gif and /dev/null differ diff --git a/icons/blue_app_rsk.gif b/icons/blue_app_rsk.gif deleted file mode 100644 index 7cd4fa050..000000000 Binary files a/icons/blue_app_rsk.gif and /dev/null differ diff --git a/icons/blue_app_rsk_testnet.gif b/icons/blue_app_rsk_testnet.gif deleted file mode 100644 index 2fd05e6b7..000000000 Binary files a/icons/blue_app_rsk_testnet.gif and /dev/null differ diff --git a/icons/blue_app_theta.gif b/icons/blue_app_theta.gif deleted file mode 100644 index 5056f1b45..000000000 Binary files a/icons/blue_app_theta.gif and /dev/null differ diff --git a/icons/blue_app_thundercore.gif b/icons/blue_app_thundercore.gif deleted file mode 100644 index bfa6ba571..000000000 Binary files a/icons/blue_app_thundercore.gif and /dev/null differ diff --git a/icons/blue_app_tobalaba.gif b/icons/blue_app_tobalaba.gif deleted file mode 100644 index d1c438fce..000000000 Binary files a/icons/blue_app_tobalaba.gif and /dev/null differ diff --git a/icons/blue_app_tomochain.gif b/icons/blue_app_tomochain.gif deleted file mode 100644 index 6ef28c768..000000000 Binary files a/icons/blue_app_tomochain.gif and /dev/null differ diff --git a/icons/blue_app_ubiq.gif b/icons/blue_app_ubiq.gif deleted file mode 100644 index 6ac116acf..000000000 Binary files a/icons/blue_app_ubiq.gif and /dev/null differ diff --git a/icons/blue_app_volta.gif b/icons/blue_app_volta.gif deleted file mode 100644 index d1c438fce..000000000 Binary files a/icons/blue_app_volta.gif and /dev/null differ diff --git a/icons/blue_app_wanchain.gif b/icons/blue_app_wanchain.gif deleted file mode 100644 index 0332113a8..000000000 Binary files a/icons/blue_app_wanchain.gif and /dev/null differ diff --git a/icons/blue_app_webchain.gif b/icons/blue_app_webchain.gif deleted file mode 100644 index 50c5b1f99..000000000 Binary files a/icons/blue_app_webchain.gif and /dev/null differ diff --git a/icons/blue_badge_thundercore.gif b/icons/blue_badge_thundercore.gif deleted file mode 100644 index a31bbe32d..000000000 Binary files a/icons/blue_badge_thundercore.gif and /dev/null differ diff --git a/icons/blue_badge_tomochain.gif b/icons/blue_badge_tomochain.gif deleted file mode 100644 index cf7c4b568..000000000 Binary files a/icons/blue_badge_tomochain.gif and /dev/null differ diff --git a/icons/callisto.png b/icons/callisto.png deleted file mode 100644 index 3319589e7..000000000 Binary files a/icons/callisto.png and /dev/null differ diff --git a/icons/dexon.png b/icons/dexon.png deleted file mode 100644 index c6a934a8f..000000000 Binary files a/icons/dexon.png and /dev/null differ diff --git a/icons/ellaism.png b/icons/ellaism.png deleted file mode 100644 index 9ea64d0bd..000000000 Binary files a/icons/ellaism.png and /dev/null differ diff --git a/icons/ether1.png b/icons/ether1.png deleted file mode 100644 index 68aec970e..000000000 Binary files a/icons/ether1.png and /dev/null differ diff --git a/icons/ethereum.png b/icons/ethereum.png deleted file mode 100755 index 60e111ce0..000000000 Binary files a/icons/ethereum.png and /dev/null differ diff --git a/icons/ethereum_classic.png b/icons/ethereum_classic.png deleted file mode 100755 index 6807e1493..000000000 Binary files a/icons/ethereum_classic.png and /dev/null differ diff --git a/icons/ethergem.png b/icons/ethergem.png deleted file mode 100644 index ad9608503..000000000 Binary files a/icons/ethergem.png and /dev/null differ diff --git a/icons/ethersocial.png b/icons/ethersocial.png deleted file mode 100644 index 5fd623f3f..000000000 Binary files a/icons/ethersocial.png and /dev/null differ diff --git a/icons/ewc.png b/icons/ewc.png deleted file mode 100644 index 5bda6b796..000000000 Binary files a/icons/ewc.png and /dev/null differ diff --git a/icons/expanse.png b/icons/expanse.png deleted file mode 100755 index 27f275cc3..000000000 Binary files a/icons/expanse.png and /dev/null differ diff --git a/icons/flare.png b/icons/flare.png deleted file mode 100644 index 57d5519e6..000000000 Binary files a/icons/flare.png and /dev/null differ diff --git a/icons/flare_coston.png b/icons/flare_coston.png deleted file mode 100644 index b732549b2..000000000 Binary files a/icons/flare_coston.png and /dev/null differ diff --git a/icons/gochain.png b/icons/gochain.png deleted file mode 100644 index 67154f805..000000000 Binary files a/icons/gochain.png and /dev/null differ diff --git a/icons/goerli.png b/icons/goerli.png deleted file mode 100755 index 60e111ce0..000000000 Binary files a/icons/goerli.png and /dev/null differ diff --git a/icons/hpb.png b/icons/hpb.png deleted file mode 100644 index 39d1d419d..000000000 Binary files a/icons/hpb.png and /dev/null differ diff --git a/icons/icon_split.gif b/icons/icon_split.gif deleted file mode 100644 index 0ab40011f..000000000 Binary files a/icons/icon_split.gif and /dev/null differ diff --git a/icons/kusd.png b/icons/kusd.png deleted file mode 100644 index e69b3fc3a..000000000 Binary files a/icons/kusd.png and /dev/null differ diff --git a/icons/mix.png b/icons/mix.png deleted file mode 100644 index 02af27ecf..000000000 Binary files a/icons/mix.png and /dev/null differ diff --git a/icons/musicoin.png b/icons/musicoin.png deleted file mode 100644 index 2d6ec90d1..000000000 Binary files a/icons/musicoin.png and /dev/null differ diff --git a/icons/nanos_app_tecracoin.gif b/icons/nanos_app_tecracoin.gif old mode 100755 new mode 100644 diff --git a/icons/nanos_app_tecratestnet.gif b/icons/nanos_app_tecratestnet.gif old mode 100755 new mode 100644 diff --git a/icons/nanox_app_tecracoin.gif b/icons/nanox_app_tecracoin.gif old mode 100755 new mode 100644 diff --git a/icons/nanox_app_tecratestnet.gif b/icons/nanox_app_tecratestnet.gif old mode 100755 new mode 100644 diff --git a/icons/pirl.png b/icons/pirl.png deleted file mode 100644 index 9ba9202fc..000000000 Binary files a/icons/pirl.png and /dev/null differ diff --git a/icons/poa.png b/icons/poa.png deleted file mode 100644 index 1443ae071..000000000 Binary files a/icons/poa.png and /dev/null differ diff --git a/icons/reosc.png b/icons/reosc.png deleted file mode 100644 index c38bbc324..000000000 Binary files a/icons/reosc.png and /dev/null differ diff --git a/icons/ropsten.png b/icons/ropsten.png deleted file mode 100755 index 60e111ce0..000000000 Binary files a/icons/ropsten.png and /dev/null differ diff --git a/icons/rsk.png b/icons/rsk.png deleted file mode 100644 index 2e8a9b4dd..000000000 Binary files a/icons/rsk.png and /dev/null differ diff --git a/icons/rsk_testnet.png b/icons/rsk_testnet.png deleted file mode 100644 index c69449b2b..000000000 Binary files a/icons/rsk_testnet.png and /dev/null differ diff --git a/icons/songbird.png b/icons/songbird.png deleted file mode 100644 index 0fd35ec03..000000000 Binary files a/icons/songbird.png and /dev/null differ diff --git a/icons/stax_app_akroma.gif b/icons/stax_app_akroma.gif new file mode 100644 index 000000000..79768660e Binary files /dev/null and b/icons/stax_app_akroma.gif differ diff --git a/icons/stax_app_apothemnetwork.gif b/icons/stax_app_apothemnetwork.gif new file mode 100644 index 000000000..381f07069 Binary files /dev/null and b/icons/stax_app_apothemnetwork.gif differ diff --git a/icons/stax_app_artis_sigma1.gif b/icons/stax_app_artis_sigma1.gif new file mode 100644 index 000000000..8d769dba2 Binary files /dev/null and b/icons/stax_app_artis_sigma1.gif differ diff --git a/icons/stax_app_artis_tau1.gif b/icons/stax_app_artis_tau1.gif new file mode 100644 index 000000000..555be4a6d Binary files /dev/null and b/icons/stax_app_artis_tau1.gif differ diff --git a/icons/stax_app_astar.gif b/icons/stax_app_astar.gif new file mode 100644 index 000000000..458e51910 Binary files /dev/null and b/icons/stax_app_astar.gif differ diff --git a/icons/stax_app_atheios.gif b/icons/stax_app_atheios.gif new file mode 100644 index 000000000..10a3e3b3b Binary files /dev/null and b/icons/stax_app_atheios.gif differ diff --git a/icons/stax_app_bsc.gif b/icons/stax_app_bsc.gif new file mode 100644 index 000000000..311d31a04 Binary files /dev/null and b/icons/stax_app_bsc.gif differ diff --git a/icons/stax_app_bttc.gif b/icons/stax_app_bttc.gif new file mode 100644 index 000000000..cc8a3f986 Binary files /dev/null and b/icons/stax_app_bttc.gif differ diff --git a/icons/stax_app_callisto.gif b/icons/stax_app_callisto.gif new file mode 100644 index 000000000..890dd9f34 Binary files /dev/null and b/icons/stax_app_callisto.gif differ diff --git a/icons/stax_app_conflux_espace.gif b/icons/stax_app_conflux_espace.gif new file mode 100644 index 000000000..e39f4425b Binary files /dev/null and b/icons/stax_app_conflux_espace.gif differ diff --git a/icons/stax_app_cube.gif b/icons/stax_app_cube.gif new file mode 100644 index 000000000..1a5b3c8e6 Binary files /dev/null and b/icons/stax_app_cube.gif differ diff --git a/icons/stax_app_dexon.gif b/icons/stax_app_dexon.gif new file mode 100644 index 000000000..692537fdd Binary files /dev/null and b/icons/stax_app_dexon.gif differ diff --git a/icons/stax_app_ellaism.gif b/icons/stax_app_ellaism.gif new file mode 100644 index 000000000..ac5ef8500 Binary files /dev/null and b/icons/stax_app_ellaism.gif differ diff --git a/icons/stax_app_energywebchain.gif b/icons/stax_app_energywebchain.gif new file mode 100644 index 000000000..3f8a57438 Binary files /dev/null and b/icons/stax_app_energywebchain.gif differ diff --git a/icons/stax_app_ether1.gif b/icons/stax_app_ether1.gif new file mode 100644 index 000000000..1f4698843 Binary files /dev/null and b/icons/stax_app_ether1.gif differ diff --git a/icons/stax_app_ethereum.gif b/icons/stax_app_ethereum.gif new file mode 100644 index 000000000..c1d6d3401 Binary files /dev/null and b/icons/stax_app_ethereum.gif differ diff --git a/icons/stax_app_ethereum_classic.gif b/icons/stax_app_ethereum_classic.gif new file mode 100644 index 000000000..10a661d87 Binary files /dev/null and b/icons/stax_app_ethereum_classic.gif differ diff --git a/icons/stax_app_ethergem.gif b/icons/stax_app_ethergem.gif new file mode 100644 index 000000000..0ed7b1cf9 Binary files /dev/null and b/icons/stax_app_ethergem.gif differ diff --git a/icons/stax_app_ethersocial.gif b/icons/stax_app_ethersocial.gif new file mode 100644 index 000000000..e8fc4dd4a Binary files /dev/null and b/icons/stax_app_ethersocial.gif differ diff --git a/icons/stax_app_expanse.gif b/icons/stax_app_expanse.gif new file mode 100644 index 000000000..9dfd8705f Binary files /dev/null and b/icons/stax_app_expanse.gif differ diff --git a/icons/stax_app_flare.gif b/icons/stax_app_flare.gif new file mode 100644 index 000000000..4d1a0f875 Binary files /dev/null and b/icons/stax_app_flare.gif differ diff --git a/icons/stax_app_flare_coston.gif b/icons/stax_app_flare_coston.gif new file mode 100644 index 000000000..2f77deea1 Binary files /dev/null and b/icons/stax_app_flare_coston.gif differ diff --git a/icons/stax_app_gochain.gif b/icons/stax_app_gochain.gif new file mode 100644 index 000000000..04bb08df6 Binary files /dev/null and b/icons/stax_app_gochain.gif differ diff --git a/icons/stax_app_goerli.gif b/icons/stax_app_goerli.gif new file mode 100644 index 000000000..95c819d26 Binary files /dev/null and b/icons/stax_app_goerli.gif differ diff --git a/icons/stax_app_hpb.gif b/icons/stax_app_hpb.gif new file mode 100644 index 000000000..4c4e50d16 Binary files /dev/null and b/icons/stax_app_hpb.gif differ diff --git a/icons/stax_app_id4good.gif b/icons/stax_app_id4good.gif new file mode 100644 index 000000000..ae3fae4a7 Binary files /dev/null and b/icons/stax_app_id4good.gif differ diff --git a/icons/stax_app_kardiachain.gif b/icons/stax_app_kardiachain.gif new file mode 100644 index 000000000..0c092ffa2 Binary files /dev/null and b/icons/stax_app_kardiachain.gif differ diff --git a/icons/stax_app_kusd.gif b/icons/stax_app_kusd.gif new file mode 100644 index 000000000..18b1a1c5e Binary files /dev/null and b/icons/stax_app_kusd.gif differ diff --git a/icons/stax_app_meter.gif b/icons/stax_app_meter.gif new file mode 100644 index 000000000..d07813d1a Binary files /dev/null and b/icons/stax_app_meter.gif differ diff --git a/icons/stax_app_mix.gif b/icons/stax_app_mix.gif new file mode 100644 index 000000000..f82aafcb9 Binary files /dev/null and b/icons/stax_app_mix.gif differ diff --git a/icons/stax_app_moonbeam.gif b/icons/stax_app_moonbeam.gif new file mode 100644 index 000000000..c8d2c9b0b Binary files /dev/null and b/icons/stax_app_moonbeam.gif differ diff --git a/icons/stax_app_moonriver.gif b/icons/stax_app_moonriver.gif new file mode 100644 index 000000000..69466a7a5 Binary files /dev/null and b/icons/stax_app_moonriver.gif differ diff --git a/icons/stax_app_multivac.gif b/icons/stax_app_multivac.gif new file mode 100644 index 000000000..ad33059e7 Binary files /dev/null and b/icons/stax_app_multivac.gif differ diff --git a/icons/stax_app_musicoin.gif b/icons/stax_app_musicoin.gif new file mode 100644 index 000000000..eced2ed72 Binary files /dev/null and b/icons/stax_app_musicoin.gif differ diff --git a/icons/stax_app_oasys.gif b/icons/stax_app_oasys.gif new file mode 100644 index 000000000..83995c697 Binary files /dev/null and b/icons/stax_app_oasys.gif differ diff --git a/icons/stax_app_okc.gif b/icons/stax_app_okc.gif new file mode 100644 index 000000000..38cfa3cc3 Binary files /dev/null and b/icons/stax_app_okc.gif differ diff --git a/icons/stax_app_pirl.gif b/icons/stax_app_pirl.gif new file mode 100644 index 000000000..6ac7154d3 Binary files /dev/null and b/icons/stax_app_pirl.gif differ diff --git a/icons/stax_app_poa.gif b/icons/stax_app_poa.gif new file mode 100644 index 000000000..afa1186ba Binary files /dev/null and b/icons/stax_app_poa.gif differ diff --git a/icons/stax_app_polygon.gif b/icons/stax_app_polygon.gif new file mode 100644 index 000000000..eba2eaad3 Binary files /dev/null and b/icons/stax_app_polygon.gif differ diff --git a/icons/stax_app_reosc.gif b/icons/stax_app_reosc.gif new file mode 100644 index 000000000..50fe3fba6 Binary files /dev/null and b/icons/stax_app_reosc.gif differ diff --git a/icons/stax_app_ropsten.gif b/icons/stax_app_ropsten.gif new file mode 100644 index 000000000..4c7a5a0e7 Binary files /dev/null and b/icons/stax_app_ropsten.gif differ diff --git a/icons/stax_app_rsk.gif b/icons/stax_app_rsk.gif new file mode 100644 index 000000000..a576134bc Binary files /dev/null and b/icons/stax_app_rsk.gif differ diff --git a/icons/stax_app_rsk_testnet.gif b/icons/stax_app_rsk_testnet.gif new file mode 100644 index 000000000..a576134bc Binary files /dev/null and b/icons/stax_app_rsk_testnet.gif differ diff --git a/icons/stax_app_shiden.gif b/icons/stax_app_shiden.gif new file mode 100644 index 000000000..132230948 Binary files /dev/null and b/icons/stax_app_shiden.gif differ diff --git a/icons/stax_app_shyft.gif b/icons/stax_app_shyft.gif new file mode 100644 index 000000000..0741eddac Binary files /dev/null and b/icons/stax_app_shyft.gif differ diff --git a/icons/stax_app_songbird.gif b/icons/stax_app_songbird.gif new file mode 100644 index 000000000..811d72ac1 Binary files /dev/null and b/icons/stax_app_songbird.gif differ diff --git a/icons/stax_app_tecracoin.gif b/icons/stax_app_tecracoin.gif new file mode 100644 index 000000000..a1ccb2d47 Binary files /dev/null and b/icons/stax_app_tecracoin.gif differ diff --git a/icons/stax_app_tecratestnet.gif b/icons/stax_app_tecratestnet.gif new file mode 100644 index 000000000..a1ccb2d47 Binary files /dev/null and b/icons/stax_app_tecratestnet.gif differ diff --git a/icons/stax_app_thundercore.gif b/icons/stax_app_thundercore.gif new file mode 100644 index 000000000..4d730a167 Binary files /dev/null and b/icons/stax_app_thundercore.gif differ diff --git a/icons/stax_app_tobalaba.gif b/icons/stax_app_tobalaba.gif new file mode 100644 index 000000000..cd3e9464e Binary files /dev/null and b/icons/stax_app_tobalaba.gif differ diff --git a/icons/stax_app_tomochain.gif b/icons/stax_app_tomochain.gif new file mode 100644 index 000000000..eb8d01a1a Binary files /dev/null and b/icons/stax_app_tomochain.gif differ diff --git a/icons/stax_app_ubiq.gif b/icons/stax_app_ubiq.gif new file mode 100644 index 000000000..afd0577ad Binary files /dev/null and b/icons/stax_app_ubiq.gif differ diff --git a/icons/stax_app_volta.gif b/icons/stax_app_volta.gif new file mode 100644 index 000000000..ea4c02447 Binary files /dev/null and b/icons/stax_app_volta.gif differ diff --git a/icons/stax_app_wanchain.gif b/icons/stax_app_wanchain.gif new file mode 100644 index 000000000..cf628048c Binary files /dev/null and b/icons/stax_app_wanchain.gif differ diff --git a/icons/stax_app_webchain.gif b/icons/stax_app_webchain.gif new file mode 100644 index 000000000..3deecb3ff Binary files /dev/null and b/icons/stax_app_webchain.gif differ diff --git a/icons/stax_app_wethio.gif b/icons/stax_app_wethio.gif new file mode 100644 index 000000000..4b540302e Binary files /dev/null and b/icons/stax_app_wethio.gif differ diff --git a/icons/stax_app_xdcnetwork.gif b/icons/stax_app_xdcnetwork.gif new file mode 100644 index 000000000..2cd15b212 Binary files /dev/null and b/icons/stax_app_xdcnetwork.gif differ diff --git a/icons/thundercore.png b/icons/thundercore.png deleted file mode 100644 index 49758acfc..000000000 Binary files a/icons/thundercore.png and /dev/null differ diff --git a/icons/tobalaba.png b/icons/tobalaba.png deleted file mode 100644 index 5bda6b796..000000000 Binary files a/icons/tobalaba.png and /dev/null differ diff --git a/icons/tomochain.png b/icons/tomochain.png deleted file mode 100644 index 9e20e2c34..000000000 Binary files a/icons/tomochain.png and /dev/null differ diff --git a/icons/ubiq.png b/icons/ubiq.png deleted file mode 100755 index b702a7b28..000000000 Binary files a/icons/ubiq.png and /dev/null differ diff --git a/icons/volta.png b/icons/volta.png deleted file mode 100644 index 5bda6b796..000000000 Binary files a/icons/volta.png and /dev/null differ diff --git a/icons/wanchain.png b/icons/wanchain.png deleted file mode 100755 index a73f62bb8..000000000 Binary files a/icons/wanchain.png and /dev/null differ diff --git a/icons/webchain.png b/icons/webchain.png deleted file mode 100644 index be97f3cec..000000000 Binary files a/icons/webchain.png and /dev/null differ diff --git a/src/common_ui.h b/src/common_ui.h index 9b2b0dc88..e14f57baf 100644 --- a/src/common_ui.h +++ b/src/common_ui.h @@ -9,7 +9,6 @@ void ui_display_public_eth2(void); void ui_display_privacy_public_key(void); void ui_display_privacy_shared_secret(void); void ui_display_public_key(void); -void ui_display_sign(void); void ui_sign_712_v0(void); void ui_display_stark_public(void); void ui_confirm_selector(void); diff --git a/src/eth_plugin_handler.c b/src/eth_plugin_handler.c index 3aa6883ef..bb73e9e1f 100644 --- a/src/eth_plugin_handler.c +++ b/src/eth_plugin_handler.c @@ -47,6 +47,8 @@ void eth_plugin_prepare_query_contract_UI(ethQueryContractUI_t *queryContractUI, uint32_t titleLength, char *msg, uint32_t msgLength) { + uint64_t chain_id; + memset((uint8_t *) queryContractUI, 0, sizeof(ethQueryContractUI_t)); // If no extra information was found, set the pointer to NULL @@ -64,7 +66,8 @@ void eth_plugin_prepare_query_contract_UI(ethQueryContractUI_t *queryContractUI, } queryContractUI->screenIndex = screenIndex; - strlcpy(queryContractUI->network_ticker, get_network_ticker(), MAX_TICKER_LEN); + chain_id = get_tx_chain_id(); + strlcpy(queryContractUI->network_ticker, get_displayable_ticker(&chain_id), MAX_TICKER_LEN); queryContractUI->title = title; queryContractUI->titleLength = titleLength; queryContractUI->msg = msg; @@ -149,7 +152,7 @@ eth_plugin_result_t eth_plugin_perform_init(uint8_t *contractAddress, } // Do not handle a plugin if running in swap mode - if (called_from_swap && (contractAddress != NULL)) { + if (G_called_from_swap && (contractAddress != NULL)) { PRINTF("eth_plug_init aborted in swap mode\n"); return 0; } diff --git a/src/eth_plugin_internal.h b/src/eth_plugin_internal.h index 692c9b609..2d2ca0369 100644 --- a/src/eth_plugin_internal.h +++ b/src/eth_plugin_internal.h @@ -7,7 +7,6 @@ #define SELECTOR_SIZE 4 #define PARAMETER_LENGTH 32 -#define RUN_APPLICATION 1 void copy_address(uint8_t* dst, const uint8_t* parameter, uint8_t dst_size); diff --git a/src/handle_swap_sign_transaction.c b/src/handle_swap_sign_transaction.c index 75e4d3a8e..604b8a26c 100644 --- a/src/handle_swap_sign_transaction.c +++ b/src/handle_swap_sign_transaction.c @@ -1,8 +1,15 @@ #include "os_io_seproxyhal.h" +#include "os.h" #include "ux.h" #include "handle_swap_sign_transaction.h" #include "shared_context.h" #include "utils.h" +#ifdef HAVE_NBGL +#include "nbgl_use_case.h" +#endif // HAVE_NBGL + +// Save the BSS address where we will write the return value when finished +static uint8_t* G_swap_sign_return_value_address; bool copy_transaction_parameters(create_transaction_parameters_t* sign_transaction_params, chain_config_t* config) { @@ -45,14 +52,30 @@ bool copy_transaction_parameters(create_transaction_parameters_t* sign_transacti stack_data.maxFee, sizeof(stack_data.maxFee)); + // Full reset the global variables + os_explicit_zero_BSS_segment(); + // Keep the address at which we'll reply the signing status + G_swap_sign_return_value_address = &sign_transaction_params->result; + // Commit the values read from exchange to the clean global space + memcpy(&strings.common, &stack_data, sizeof(stack_data)); return true; } +void __attribute__((noreturn)) finalize_exchange_sign_transaction(bool is_success) { + *G_swap_sign_return_value_address = is_success; + os_lib_end(); +} + void handle_swap_sign_transaction(chain_config_t* config) { + UX_INIT(); +#ifdef HAVE_NBGL + nbgl_useCaseSpinner("Signing"); +#endif // HAVE_NBGL + chainConfig = config; reset_app_context(); - called_from_swap = true; + G_called_from_swap = true; io_seproxyhal_init(); if (N_storage.initialized != 0x01) { @@ -65,18 +88,15 @@ void handle_swap_sign_transaction(chain_config_t* config) { nvm_write((void*) &N_storage, (void*) &storage, sizeof(internalStorage_t)); } - UX_INIT(); USB_power(0); USB_power(1); // ui_idle(); PRINTF("USB power ON/OFF\n"); -#ifdef TARGET_NANOX +#ifdef HAVE_BLE // grab the current plane mode setting G_io_app.plane_mode = os_setting_get(OS_SETTING_PLANEMODE, NULL, 0); -#endif // TARGET_NANOX -#ifdef HAVE_BLE BLE_power(0, NULL); - BLE_power(1, "Nano X"); + BLE_power(1, NULL); #endif // HAVE_BLE app_main(); } diff --git a/src/handle_swap_sign_transaction.h b/src/handle_swap_sign_transaction.h index 21b52c356..d34a6d860 100644 --- a/src/handle_swap_sign_transaction.h +++ b/src/handle_swap_sign_transaction.h @@ -1,5 +1,4 @@ -#ifndef _HANDLE_SWAP_SIGN_TRANSACTION_H_ -#define _HANDLE_SWAP_SIGN_TRANSACTION_H_ +#pragma once #include "swap_lib_calls.h" #include "chainConfig.h" @@ -9,4 +8,4 @@ bool copy_transaction_parameters(create_transaction_parameters_t* sign_transacti void handle_swap_sign_transaction(chain_config_t* config); -#endif // _HANDLE_SWAP_SIGN_TRANSACTION_H_ \ No newline at end of file +void __attribute__((noreturn)) finalize_exchange_sign_transaction(bool is_success); diff --git a/src/main.c b/src/main.c index a483bf401..3399b8614 100644 --- a/src/main.c +++ b/src/main.c @@ -52,7 +52,7 @@ cx_sha3_t global_sha3; uint8_t appState; uint16_t apdu_response_code; -bool called_from_swap; +bool G_called_from_swap; pluginType_t pluginType; #ifdef HAVE_STARKWARE bool quantumSet; @@ -69,12 +69,15 @@ bolos_ux_params_t G_ux_params; const internalStorage_t N_storage_real; -chain_config_t *chainConfig; +#ifdef HAVE_NBGL +caller_app_t *caller_app = NULL; +#endif +chain_config_t *chainConfig = NULL; void reset_app_context() { // PRINTF("!!RESET_APP_CONTEXT\n"); appState = APP_STATE_IDLE; - called_from_swap = false; + G_called_from_swap = false; pluginType = OLD_INTERNAL; #ifdef HAVE_STARKWARE quantumSet = false; @@ -877,9 +880,11 @@ void app_main(void) { } // override point, but nothing more to do +#ifdef HAVE_BAGL void io_seproxyhal_display(const bagl_element_t *element) { io_seproxyhal_display_default((bagl_element_t *) element); } +#endif unsigned char io_event(__attribute__((unused)) unsigned char channel) { // nothing done with the event, throw an error on the transport layer if @@ -890,10 +895,11 @@ unsigned char io_event(__attribute__((unused)) unsigned char channel) { case SEPROXYHAL_TAG_FINGER_EVENT: UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer); break; - +#ifdef HAVE_BAGL case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT: UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer); break; +#endif // HAVE_BAGL case SEPROXYHAL_TAG_STATUS_EVENT: if (G_io_apdu_media == IO_APDU_MEDIA_USB_HID && @@ -901,22 +907,23 @@ unsigned char io_event(__attribute__((unused)) unsigned char channel) { SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED)) { THROW(EXCEPTION_IO_RESET); } - // no break is intentional + __attribute__((fallthrough)); default: UX_DEFAULT_EVENT(); break; case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT: +#ifdef HAVE_BAGL UX_DISPLAYED_EVENT({}); +#endif // HAVE_BAGL +#ifdef HAVE_NBGL + UX_DEFAULT_EVENT(); +#endif // HAVE_NBGL break; -#if 0 - case SEPROXYHAL_TAG_TICKER_EVENT: - UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, - { - }); - break; -#endif + case SEPROXYHAL_TAG_TICKER_EVENT: + UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {}); + break; } // close the event if not done previously (by a display or whatever) @@ -946,14 +953,27 @@ void init_coin_config(chain_config_t *coin_config) { coin_config->kind = CHAIN_KIND; } -void coin_main(chain_config_t *coin_config) { +void coin_main(libargs_t *args) { chain_config_t config; - if (coin_config == NULL) { + if (args) { + if (args->chain_config != NULL) { + chainConfig = args->chain_config; + } +#ifdef HAVE_NBGL + if ((caller_app = args->caller_app) != NULL) { + if (chainConfig != NULL) { + caller_app->type = CALLER_TYPE_CLONE; + } else { + caller_app->type = CALLER_TYPE_PLUGIN; + } + } +#endif + } + if (chainConfig == NULL) { init_coin_config(&config); chainConfig = &config; - } else { - chainConfig = coin_config; } + reset_app_context(); tmpCtx.transactionContext.currentItemIndex = 0; @@ -964,10 +984,10 @@ void coin_main(chain_config_t *coin_config) { TRY { io_seproxyhal_init(); -#ifdef TARGET_NANOX +#ifdef HAVE_BLE // grab the current plane mode setting G_io_app.plane_mode = os_setting_get(OS_SETTING_PLANEMODE, NULL, 0); -#endif // TARGET_NANOX +#endif // HAVE_BLE if (!N_storage.initialized) { internalStorage_t storage; @@ -995,7 +1015,7 @@ void coin_main(chain_config_t *coin_config) { #ifdef HAVE_BLE BLE_power(0, NULL); - BLE_power(1, "Nano X"); + BLE_power(1, NULL); #endif // HAVE_BLE #ifdef HAVE_DOMAIN_NAME @@ -1022,18 +1042,7 @@ void coin_main(chain_config_t *coin_config) { app_exit(); } -struct libargs_s { - unsigned int id; - unsigned int command; - chain_config_t *chain_config; - union { - check_address_parameters_t *check_address; - create_transaction_parameters_t *create_transaction; - get_printable_amount_parameters_t *get_printable_amount; - }; -}; - -static void library_main_helper(struct libargs_s *args) { +static void library_main_helper(libargs_t *args) { check_api_level(CX_COMPAT_APILEVEL); PRINTF("Inside a library \n"); switch (args->command) { @@ -1061,13 +1070,13 @@ static void library_main_helper(struct libargs_s *args) { } } -void library_main(struct libargs_s *args) { +void library_main(libargs_t *args) { chain_config_t coin_config; if (args->chain_config == NULL) { init_coin_config(&coin_config); args->chain_config = &coin_config; } - bool end = false; + volatile bool end = false; /* This loop ensures that library_main_helper and os_lib_end are called * within a try context, even if an exception is thrown */ while (1) { @@ -1093,6 +1102,7 @@ __attribute__((section(".boot"))) int main(int arg0) { unsigned int libcall_params[5]; chain_config_t local_chainConfig; init_coin_config(&local_chainConfig); + PRINTF("Hello from Eth-clone\n"); check_api_level(CX_COMPAT_APILEVEL); // delegate to Ethereum app/lib @@ -1100,7 +1110,22 @@ __attribute__((section(".boot"))) int main(int arg0) { libcall_params[1] = 0x100; libcall_params[2] = RUN_APPLICATION; libcall_params[3] = (unsigned int) &local_chainConfig; - libcall_params[4] = 0; +#ifdef HAVE_NBGL + const char app_name[] = APPNAME; + caller_app_t capp; + nbgl_icon_details_t icon_details; + uint8_t bitmap[sizeof(ICONBITMAP)]; + + memcpy(&icon_details, &ICONGLYPH, sizeof(ICONGLYPH)); + memcpy(&bitmap, &ICONBITMAP, sizeof(bitmap)); + icon_details.bitmap = (const uint8_t *) bitmap; + capp.name = app_name; + capp.icon = &icon_details; + libcall_params[4] = (unsigned int) &capp; +#else + libcall_params[4] = NULL; +#endif // HAVE_NBGL + if (arg0) { // call as a library libcall_params[2] = ((unsigned int *) arg0)[1]; @@ -1132,7 +1157,7 @@ __attribute__((section(".boot"))) int main(int arg0) { return 0; } - struct libargs_s *args = (struct libargs_s *) arg0; + libargs_t *args = (libargs_t *) arg0; if (args->id != 0x100) { app_exit(); return 0; @@ -1140,7 +1165,7 @@ __attribute__((section(".boot"))) int main(int arg0) { switch (args->command) { case RUN_APPLICATION: // called as ethereum from altcoin or plugin - coin_main(args->chain_config); + coin_main(args); break; default: // called as ethereum or altcoin library diff --git a/src/shared_context.h b/src/shared_context.h index ce907ddd9..f83320cb5 100644 --- a/src/shared_context.h +++ b/src/shared_context.h @@ -7,6 +7,9 @@ #include "tokens.h" #include "chainConfig.h" #include "nft.h" +#ifdef HAVE_NBGL +#include "nbgl_types.h" +#endif #define MAX_BIP32_PATH 10 @@ -210,7 +213,7 @@ extern strings_t strings; extern cx_sha3_t global_sha3; extern const internalStorage_t N_storage_real; -extern bool called_from_swap; +extern bool G_called_from_swap; typedef enum { EXTERNAL, // External plugin, set by setExternalPlugin. @@ -221,6 +224,16 @@ typedef enum { extern pluginType_t pluginType; +typedef enum { CALLER_TYPE_CLONE, CALLER_TYPE_PLUGIN } e_caller_type; + +typedef struct caller_app_t { + const char *name; +#ifdef HAVE_NBGL + const nbgl_icon_details_t *icon; +#endif + char type; // does not have to be set by the caller app +} caller_app_t; + extern uint8_t appState; #ifdef HAVE_STARKWARE extern bool quantumSet; @@ -229,6 +242,8 @@ extern bool quantumSet; extern uint32_t eth2WithdrawalIndex; #endif +extern caller_app_t *caller_app; + void reset_app_context(void); const uint8_t *parseBip32(const uint8_t *dataBuffer, uint8_t *dataLength, bip32_path_t *bip32); diff --git a/src/swap_lib_calls.h b/src/swap_lib_calls.h index 9bdb11522..287034707 100644 --- a/src/swap_lib_calls.h +++ b/src/swap_lib_calls.h @@ -1,7 +1,15 @@ -#ifndef _SWAP_LIB_CALLS_H_ -#define _SWAP_LIB_CALLS_H_ +#pragma once + +/* This file is the shared API between Exchange and the apps started in Library mode for Exchange + * + * DO NOT MODIFY THIS FILE IN APPLICATIONS OTHER THAN EXCHANGE + * On modification in Exchange, forward the changes to all applications supporting Exchange + */ #include "stdbool.h" +#include "chainConfig.h" +#include "shared_context.h" +#include "stdint.h" #define RUN_APPLICATION 1 @@ -11,19 +19,27 @@ #define GET_PRINTABLE_AMOUNT 4 +/* + * Amounts are stored as bytes, with a max size of 16 (see protobuf + * specifications). Max 16B integer is 340282366920938463463374607431768211455 + * in decimal, which is a 32-long char string. + * The printable amount also contains spaces, the ticker symbol (with variable + * size, up to 12 in Ethereum for instance) and a terminating null byte, so 50 + * bytes total should be a fair maximum. + */ #define MAX_PRINTABLE_AMOUNT_SIZE 50 // structure that should be send to specific coin application to get address typedef struct check_address_parameters_s { // IN - const unsigned char* const coin_configuration; - const unsigned char coin_configuration_length; + uint8_t *coin_configuration; + uint8_t coin_configuration_length; // serialized path, segwit, version prefix, hash used, dictionary etc. - // fields and serialization format depends on spesific coin app - const unsigned char* const address_parameters; - const unsigned char address_parameters_length; - const char* const address_to_check; - const char* const extra_id_to_check; + // fields and serialization format depends on specific coin app + uint8_t *address_parameters; + uint8_t address_parameters_length; + char *address_to_check; + char *extra_id_to_check; // OUT int result; } check_address_parameters_t; @@ -31,25 +47,37 @@ typedef struct check_address_parameters_s { // structure that should be send to specific coin application to get printable amount typedef struct get_printable_amount_parameters_s { // IN - const unsigned char* const coin_configuration; - const unsigned char coin_configuration_length; - const unsigned char* const amount; - const unsigned char amount_length; - const bool is_fee; + uint8_t *coin_configuration; + uint8_t coin_configuration_length; + uint8_t *amount; + uint8_t amount_length; + bool is_fee; // OUT char printable_amount[MAX_PRINTABLE_AMOUNT_SIZE]; - // int result; } get_printable_amount_parameters_t; typedef struct create_transaction_parameters_s { - const unsigned char* const coin_configuration; - const unsigned char coin_configuration_length; - const unsigned char* const amount; - const unsigned char amount_length; - const unsigned char* const fee_amount; - const unsigned char fee_amount_length; - const char* const destination_address; - const char* const destination_address_extra_id; + // IN + uint8_t *coin_configuration; + uint8_t coin_configuration_length; + uint8_t *amount; + uint8_t amount_length; + uint8_t *fee_amount; + uint8_t fee_amount_length; + char *destination_address; + char *destination_address_extra_id; + // OUT + uint8_t result; } create_transaction_parameters_t; -#endif // _SWAP_LIB_CALLS_H_ +typedef struct libargs_s { + unsigned int id; + unsigned int command; + chain_config_t *chain_config; + union { + check_address_parameters_t *check_address; + create_transaction_parameters_t *create_transaction; + get_printable_amount_parameters_t *get_printable_amount; + caller_app_t *caller_app; + }; +} libargs_t; diff --git a/src/tokens.c b/src/tokens.c index e17e482c8..a513758bd 100644 --- a/src/tokens.c +++ b/src/tokens.c @@ -24,36 +24,36 @@ const tokenDefinition_t TOKENS_EXTRA[NUM_TOKENS_EXTRA] = { // Ropsten DeversiFi tokens {{0x4c, 0x5f, 0x66, 0x59, 0x61, 0x97, 0xa8, 0x6f, 0xb3, 0x0a, 0x24, 0x35, 0xe2, 0xef, 0x4d, 0xdc, 0xb3, 0x93, 0x42, 0xc9}, - "tUSDT ", + "tUSDT", 6}, {{0x1c, 0x0f, 0x17, 0x43, 0x67, 0x40, 0xbf, 0xb9, 0x2c, 0x10, 0x70, 0xee, 0x86, 0x32, 0x2d, 0xe8, 0x90, 0x83, 0x7c, 0x6a}, - "tUSDT ", + "tUSDT", 6}, {{0xcd, 0x07, 0x7a, 0xbe, 0xdd, 0x83, 0x1a, 0x34, 0x43, 0xff, 0xbe, 0x24, 0xfb, 0x76, 0x66, 0x1b, 0xbb, 0x17, 0xeb, 0x69}, - "tZRX ", + "tZRX", 18}, {{0x40, 0xd8, 0x97, 0x85, 0x00, 0xbf, 0x68, 0x32, 0x4a, 0x51, 0x53, 0x3c, 0xd6, 0xa2, 0x1e, 0x3e, 0x59, 0xbe, 0x32, 0x4a}, - "tBTC ", + "tBTC", 18}, // Goerli DeversiFi tokens {{0xd9, 0x97, 0xa8, 0x63, 0x46, 0xe7, 0x65, 0x18, 0xe6, 0x92, 0x25, 0x56, 0xf3, 0x4d, 0x76, 0x61, 0x30, 0xc0, 0xbb, 0xfd}, - "tUSDT ", + "tUSDT", 6}, {{0xc1, 0xd5, 0x79, 0xeb, 0xff, 0x7c, 0x0f, 0x6c, 0xfd, 0x9a, 0xd5, 0xfb, 0x26, 0x7f, 0xec, 0x73, 0xbe, 0x70, 0xc8, 0xf7}, - "tBTC ", + "tBTC", 18}, {{0xa8, 0xf3, 0x14, 0x4f, 0xea, 0x2c, 0x37, 0x5a, 0xd0, 0x58, 0xec, 0x12, 0x09, 0x9a, 0x5a, 0x21, 0xa2, 0x6f, 0xe9, 0x96}, - "tDVF ", + "tDVF", 18}, {{0x4c, 0xda, 0xbe, 0xc1, 0x2a, 0x39, 0x7f, 0xb6, 0xef, 0xaf, 0x46, 0x13, 0xd5, 0xdf, 0xd7, 0x9b, 0x30, 0x9a, 0xe9, 0xfa}, - "tXDVF ", + "tXDVF", 18}, }; @@ -69,11 +69,11 @@ const tokenDefinition_t TOKENS_EXTRA[NUM_TOKENS_EXTRA] = { const tokenDefinition_t const TOKENS_ETHEREUM[NUM_TOKENS_ETHEREUM] = { {{0xdb, 0x25, 0xf2, 0x11, 0xab, 0x05, 0xb1, 0xc9, 0x7d, 0x59, 0x55, 0x16, 0xf4, 0x57, 0x94, 0x52, 0x8a, 0x80, 0x7a, 0xd8}, - "EURS ", + "EURS", 2}, {{0xa7, 0x44, 0x76, 0x44, 0x31, 0x19, 0xA9, 0x42, 0xdE, 0x49, 0x85, 0x90, 0xFe, 0x1f, 0x24, 0x54, 0xd7, 0xD4, 0xaC, 0x0d}, - "GNT ", + "GNT", 18}, }; @@ -89,19 +89,19 @@ const tokenDefinition_t const TOKENS_ELLAISM[NUM_TOKENS_ELLAISM] = { const tokenDefinition_t const TOKENS_ETHEREUM_CLASSIC[NUM_TOKENS_ETHEREUM_CLASSIC] = { {{0x6F, 0x6D, 0xEb, 0x5d, 0xb0, 0xC4, 0x99, 0x4A, 0x82, 0x83, 0xA0, 0x1D, 0x6C, 0xFe, 0xEB, 0x27, 0xFc, 0x3b, 0xBe, 0x9C}, - "Smart ", + "Smart", 0}, {{0x08, 0x5f, 0xb4, 0xf2, 0x40, 0x31, 0xea, 0xed, 0xbc, 0x2b, 0x61, 0x1a, 0xa5, 0x28, 0xf2, 0x23, 0x43, 0xeb, 0x52, 0xdb}, - "BEC ", + "BEC", 8}, {{0x5a, 0xce, 0x17, 0xf8, 0x7c, 0x73, 0x91, 0xe5, 0x79, 0x2a, 0x76, 0x83, 0x06, 0x9a, 0x80, 0x25, 0xb8, 0x3b, 0xbd, 0x85}, - "PLAY ", + "PLAY", 0}, {{0x6A, 0xDa, 0x6F, 0x48, 0xC8, 0x15, 0x68, 0x95, 0x02, 0xC4, 0x3e, 0xC1, 0xa5, 0x9F, 0x1b, 0x5D, 0xD3, 0xC0, 0x4E, 0x1F}, - "UNV ", + "UNV", 18}, }; @@ -118,27 +118,27 @@ const tokenDefinition_t const TOKENS_RSK[NUM_TOKENS_RSK] = {}; const tokenDefinition_t const TOKENS_UBIQ[NUM_TOKENS_UBIQ] = { {{0xd2, 0x45, 0x20, 0x7c, 0xfb, 0xf6, 0xeb, 0x6f, 0x34, 0x97, 0x0d, 0xb2, 0xa8, 0x07, 0xab, 0x1d, 0x17, 0x8f, 0xde, 0x6c}, - "APX ", + "APX", 8}, {{0xff, 0x3b, 0xf0, 0x57, 0xad, 0xf3, 0xb0, 0xe0, 0x15, 0xb6, 0x46, 0x53, 0x31, 0xa6, 0x23, 0x6e, 0x55, 0x68, 0x82, 0x74}, - "BEER ", + "BEER", 0}, {{0x08, 0x53, 0x3d, 0x6a, 0x06, 0xce, 0x36, 0x52, 0x98, 0xb1, 0x2e, 0xf9, 0x2e, 0xb4, 0x07, 0xcb, 0xa8, 0xaa, 0x82, 0x73}, - "CEFS ", + "CEFS", 8}, {{0x94, 0xad, 0x7e, 0x41, 0xc1, 0xd4, 0x40, 0x22, 0xc4, 0xf4, 0x7c, 0xb1, 0xba, 0x01, 0x9f, 0xd1, 0xa0, 0x22, 0xc5, 0x36}, - "DOT ", + "DOT", 8}, {{0x4b, 0x48, 0x99, 0xa1, 0x0f, 0x3e, 0x50, 0x7d, 0xb2, 0x07, 0xb0, 0xee, 0x24, 0x26, 0x02, 0x9e, 0xfa, 0x16, 0x8a, 0x67}, - "QWARK ", + "QWARK", 8}, {{0x5e, 0x17, 0x15, 0xbb, 0x79, 0x80, 0x5b, 0xd6, 0x72, 0x72, 0x97, 0x60, 0xb3, 0xf7, 0xf3, 0x4d, 0x6f, 0x48, 0x50, 0x98}, - "RICKS ", + "RICKS", 8}, }; diff --git a/src/ui_callbacks.h b/src/ui_callbacks.h index 2035c27a9..041f7173e 100644 --- a/src/ui_callbacks.h +++ b/src/ui_callbacks.h @@ -4,6 +4,10 @@ #include "shared_context.h" #include "ux.h" +#ifdef HAVE_NBGL +typedef int bagl_element_t; +#endif + unsigned int io_seproxyhal_touch_settings(const bagl_element_t *e); unsigned int io_seproxyhal_touch_exit(const bagl_element_t *e); unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e); diff --git a/src_bagl/ui_flow_signTx.c b/src_bagl/ui_flow_signTx.c index 2b5592207..5d8e7b394 100644 --- a/src_bagl/ui_flow_signTx.c +++ b/src_bagl/ui_flow_signTx.c @@ -7,6 +7,7 @@ #include "eth_plugin_handler.h" #include "ui_plugin.h" #include "common_ui.h" +#include "ethUtils.h" #include "plugins.h" #include "domain_name.h" #include "ui_domain_name.h" @@ -220,7 +221,7 @@ void ux_approve_tx(bool fromPlugin) { // We're in a regular transaction, just show the amount and the address ux_approval_tx_flow[step++] = &ux_approval_amount_step; #ifdef HAVE_DOMAIN_NAME - uint64_t chain_id = get_chain_id(); + uint64_t chain_id = get_tx_chain_id(); if (has_domain_name(&chain_id, tmpContent.txContent.destination)) { ux_approval_tx_flow[step++] = &ux_domain_name_step; if (N_storage.verbose_domain_name) { @@ -238,7 +239,7 @@ void ux_approve_tx(bool fromPlugin) { ux_approval_tx_flow[step++] = &ux_approval_nonce_step; } - uint64_t chain_id = get_chain_id(); + uint64_t chain_id = get_tx_chain_id(); if (chainConfig->chainId == ETHEREUM_MAINNET_CHAINID && chain_id != chainConfig->chainId) { ux_approval_tx_flow[step++] = &ux_approval_network_step; } diff --git a/src_common/ethUtils.c b/src_common/ethUtils.c index 4dd0e6a57..e66e0d2e5 100644 --- a/src_common/ethUtils.c +++ b/src_common/ethUtils.c @@ -27,9 +27,12 @@ #include #include +#include "shared_context.h" +#include "utils.h" #include "ethUtils.h" #include "chainConfig.h" #include "ethUstream.h" +#include "network.h" bool rlpCanDecode(uint8_t *buffer, uint32_t bufferLength, bool *valid) { if (*buffer <= 0x7f) { @@ -301,3 +304,32 @@ bool adjustDecimals(const char *src, } return true; } + +// Returns the chain ID. Defaults to 0 if txType was not found (For TX). +uint64_t get_tx_chain_id(void) { + uint64_t chain_id = 0; + + switch (txContext.txType) { + case LEGACY: + chain_id = u64_from_BE(txContext.content->v, txContext.content->vLength); + break; + case EIP2930: + case EIP1559: + chain_id = u64_from_BE(tmpContent.txContent.chainID.value, + tmpContent.txContent.chainID.length); + break; + default: + PRINTF("Txtype `%d` not supported while generating chainID\n", txContext.txType); + break; + } + return chain_id; +} + +const char *get_displayable_ticker(const uint64_t *chain_id) { + const char *ticker = get_network_ticker_from_chain_id(chain_id); + + if (ticker == NULL) { + ticker = chainConfig->coinName; + } + return ticker; +} diff --git a/src_common/ethUtils.h b/src_common/ethUtils.h index 9722e2c43..870253351 100644 --- a/src_common/ethUtils.h +++ b/src_common/ethUtils.h @@ -84,6 +84,10 @@ static __attribute__((no_instrument_function)) inline int ismaxint(uint8_t *buf, return 1; } +uint64_t get_tx_chain_id(void); + +const char *get_displayable_ticker(const uint64_t *chain_id); + static const char HEXDIGITS[] = "0123456789abcdef"; #endif // _ETHUTILS_H_ diff --git a/src_common/network.c b/src_common/network.c index f0dc4d1e5..8c0d238a6 100644 --- a/src_common/network.c +++ b/src_common/network.c @@ -1,11 +1,13 @@ -#include -#include -#include #include +#include "os_utils.h" +#include "os_pic.h" #include "network.h" -#include "os.h" -#include "shared_context.h" -#include "utils.h" + +typedef struct network_info_s { + const char *name; + const char *ticker; + uint64_t chain_id; +} network_info_t; // Mappping of chain ids to networks. static const network_info_t NETWORK_MAPPING[] = { @@ -14,9 +16,11 @@ static const network_info_t NETWORK_MAPPING[] = { {.chain_id = 4, .name = "Rinkeby", .ticker = "ETH"}, {.chain_id = 5, .name = "Goerli", .ticker = "ETH"}, {.chain_id = 10, .name = "Optimism", .ticker = "ETH"}, - {.chain_id = 42, .name = "Kovan", .ticker = "ETH"}, + {.chain_id = 42, .name = "LUKSO", .ticker = "LYX"}, + {.chain_id = 4201, .name = "LUKSO Testnet", .ticker = "LYXt"}, {.chain_id = 56, .name = "BSC", .ticker = "BNB"}, - {.chain_id = 100, .name = "xDai", .ticker = "xDAI"}, + {.chain_id = 100, .name = "Gnosis", .ticker = "xDAI"}, + {.chain_id = 10200, .name = "Chiado", .ticker = "xDAI"}, {.chain_id = 137, .name = "Polygon", .ticker = "MATIC"}, {.chain_id = 250, .name = "Fantom", .ticker = "FTM"}, {.chain_id = 42161, .name = "Arbitrum", .ticker = "ETH"}, @@ -62,51 +66,45 @@ static const network_info_t NETWORK_MAPPING[] = { {.chain_id = 106, .name = "Velas EVM", .ticker = "VLX"}, {.chain_id = 288, .name = "Boba Network", .ticker = "ETH"}, {.chain_id = 39797, .name = "Energi", .ticker = "NRG"}, - {.chain_id = 248, .name = "Oasys", .ticker = "OAS"}}; - -uint64_t get_chain_id(void) { - uint64_t chain_id = 0; - - switch (txContext.txType) { - case LEGACY: - chain_id = u64_from_BE(txContext.content->v, txContext.content->vLength); - break; - case EIP2930: - case EIP1559: - chain_id = u64_from_BE(tmpContent.txContent.chainID.value, - tmpContent.txContent.chainID.length); - break; - default: - PRINTF("Txtype `%d` not supported while generating chainID\n", txContext.txType); - break; - } - return chain_id; -} + {.chain_id = 369, .name = "PulseChain", .ticker = "PLS"}, + {.chain_id = 245022926, .name = "Neon EVM Devnet", .ticker = "NEON"}, + {.chain_id = 245022934, .name = "Neon EVM Mainnet", .ticker = "NEON"}, + {.chain_id = 4919, .name = "Venidium", .ticker = "XVM"}, + {.chain_id = 40, .name = "Telos EVM Mainnet", .ticker = "TLOS"}, + {.chain_id = 196, .name = "OKBChain Mainnet", .ticker = "OKB"}, + {.chain_id = 248, .name = "Oasys", .ticker = "OAS"}, + {.chain_id = 1101, .name = "Polygon zkEVM", .ticker = "ETH"}, + {.chain_id = 8453, .name = "Base", .ticker = "ETH"}, + {.chain_id = 58008, .name = "Sepolia", .ticker = "ETH"}, +}; -const network_info_t *get_network(void) { - uint64_t chain_id = get_chain_id(); - for (size_t i = 0; i < sizeof(NETWORK_MAPPING) / sizeof(*NETWORK_MAPPING); i++) { - if (NETWORK_MAPPING[i].chain_id == chain_id) { - return (const network_info_t *) PIC(&NETWORK_MAPPING[i]); +static const network_info_t *get_network_from_chain_id(const uint64_t *chain_id) { + for (size_t i = 0; i < ARRAYLEN(NETWORK_MAPPING); i++) { + if (NETWORK_MAPPING[i].chain_id == *chain_id) { + return (const network_info_t *) &NETWORK_MAPPING[i]; } } return NULL; } -const char *get_network_name(void) { - const network_info_t *network = get_network(); - if (network == NULL) { +const char *get_network_name_from_chain_id(const uint64_t *chain_id) { + const network_info_t *net = get_network_from_chain_id(chain_id); + + if (net == NULL) { return NULL; - } else { - return (const char *) PIC(network->name); } + return PIC(net->name); } -const char *get_network_ticker(void) { - const network_info_t *network = get_network(); - if (network == NULL) { - return chainConfig->coinName; - } else { - return (char *) PIC(network->ticker); +const char *get_network_ticker_from_chain_id(const uint64_t *chain_id) { + const network_info_t *net = get_network_from_chain_id(chain_id); + + if (net == NULL) { + return NULL; } + return PIC(net->ticker); +} + +bool chain_is_ethereum_compatible(const uint64_t *chain_id) { + return get_network_from_chain_id(chain_id) != NULL; } diff --git a/src_common/network.h b/src_common/network.h index b9ce7f31a..8361bcb9a 100644 --- a/src_common/network.h +++ b/src_common/network.h @@ -2,22 +2,11 @@ #define _NETWORK_H_ #include -#include "tokens.h" -#include "shared_context.h" +#include -typedef struct network_info_s { - const char *name; - const char *ticker; - uint64_t chain_id; -} network_info_t; +const char *get_network_name_from_chain_id(const uint64_t *chain_id); +const char *get_network_ticker_from_chain_id(const uint64_t *chain_id); -// Returns the current chain id. Defaults to 0 if txType was not found. -uint64_t get_chain_id(void); -// Returns a pointer to the network struct, or NULL if there is none. -const network_info_t *get_network(void); -// Returns a pointer to the network name, or NULL if there is none. -const char *get_network_name(void); -// Returns a pointer to the network ticker, or chainConfig->coinName if there is none. -const char *get_network_ticker(void); +bool chain_is_ethereum_compatible(const uint64_t *chain_id); #endif // _NETWORK_H_ diff --git a/src_features/getEth2PublicKey/cmd_getEth2PublicKey.c b/src_features/getEth2PublicKey/cmd_getEth2PublicKey.c index 853d834fe..b1b38d5f1 100644 --- a/src_features/getEth2PublicKey/cmd_getEth2PublicKey.c +++ b/src_features/getEth2PublicKey/cmd_getEth2PublicKey.c @@ -49,7 +49,7 @@ void handleGetEth2PublicKey(uint8_t p1, unsigned int *tx) { bip32_path_t bip32; - if (!called_from_swap) { + if (!G_called_from_swap) { reset_app_context(); } if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) { diff --git a/src_features/getPublicKey/cmd_getPublicKey.c b/src_features/getPublicKey/cmd_getPublicKey.c index 07bab1df0..bc8bac6ce 100644 --- a/src_features/getPublicKey/cmd_getPublicKey.c +++ b/src_features/getPublicKey/cmd_getPublicKey.c @@ -16,7 +16,7 @@ void handleGetPublicKey(uint8_t p1, bip32_path_t bip32; cx_ecfp_private_key_t privateKey; - if (!called_from_swap) { + if (!G_called_from_swap) { reset_app_context(); } diff --git a/src_features/provideDomainName/cmd_provide_domain_name.c b/src_features/provideDomainName/cmd_provide_domain_name.c index 0d0849f26..e1d14a49c 100644 --- a/src_features/provideDomainName/cmd_provide_domain_name.c +++ b/src_features/provideDomainName/cmd_provide_domain_name.c @@ -10,6 +10,7 @@ #include "challenge.h" #include "mem.h" #include "hash_bytes.h" +#include "network.h" static const uint8_t DOMAIN_NAME_PUB_KEY[] = { #ifdef HAVE_DOMAIN_NAME_TEST_KEY @@ -124,8 +125,8 @@ bool has_domain_name(const uint64_t *chain_id, const uint8_t *addr) { bool ret = false; if (g_domain_name_info.valid) { - // TODO: Remove once other domain name providers are supported - if ((*chain_id == ETHEREUM_MAINNET_CHAINID) && + // Check if chain ID is known to be Ethereum-compatible (same derivation path) + if ((chain_is_ethereum_compatible(chain_id)) && (memcmp(addr, g_domain_name_info.addr, ADDRESS_LENGTH) == 0)) { ret = true; } @@ -478,7 +479,7 @@ static bool parse_der_value(const s_tlv_payload *payload, size_t *offset, uint32 if ((*offset + byte_length) > payload->size) { PRINTF("TLV payload too small for DER encoded value\n"); } else { - if (byte_length > sizeof(buf)) { + if (byte_length > sizeof(buf) || byte_length == 0) { PRINTF("Unexpectedly long DER-encoded value (%u bytes)\n", byte_length); } else { memset(buf, 0, (sizeof(buf) - byte_length)); diff --git a/src_features/signMessageEIP712/commands_712.c b/src_features/signMessageEIP712/commands_712.c index 7810b9335..a1cc45f9a 100644 --- a/src_features/signMessageEIP712/commands_712.c +++ b/src_features/signMessageEIP712/commands_712.c @@ -13,7 +13,8 @@ #include "schema_hash.h" #include "filtering.h" #include "common_712.h" -#include "ethUtils.h" // allzeroes +#include "ethUtils.h" // allzeroes +#include "common_ui.h" // ui_idle /** * Send the response to the previous APDU command @@ -38,6 +39,7 @@ void handle_eip712_return_code(bool success) { if (!success) { eip712_context_deinit(); + ui_idle(); } } diff --git a/src_features/signMessageEIP712/context_712.c b/src_features/signMessageEIP712/context_712.c index 82abd0935..57d5be6dd 100644 --- a/src_features/signMessageEIP712/context_712.c +++ b/src_features/signMessageEIP712/context_712.c @@ -72,7 +72,6 @@ void eip712_context_deinit(void) { mem_reset(); eip712_context = NULL; reset_app_context(); - ui_idle(); } #endif diff --git a/src_features/signMessageEIP712/path.c b/src_features/signMessageEIP712/path.c index ec95242c8..621d11dc5 100644 --- a/src_features/signMessageEIP712/path.c +++ b/src_features/signMessageEIP712/path.c @@ -143,14 +143,18 @@ static cx_sha3_t *get_last_hash_ctx(void) { * Finalize the last hashing context * * @param[out] hash pointer to buffer where the hash will be stored + * @return whether there was anything hashed at this depth */ -static void finalize_hash_depth(uint8_t *hash) { +static bool finalize_hash_depth(uint8_t *hash) { const cx_sha3_t *hash_ctx; + size_t hashed_bytes; hash_ctx = get_last_hash_ctx(); + hashed_bytes = hash_ctx->blen; // finalize hash cx_hash((cx_hash_t *) hash_ctx, CX_LAST, NULL, 0, hash, KECCAK256_HASH_BYTESIZE); mem_dealloc(sizeof(*hash_ctx)); // remove hash context + return hashed_bytes > 0; } /** @@ -192,6 +196,7 @@ static bool push_new_hash_depth(bool init) { */ static bool path_depth_list_pop(void) { uint8_t hash[KECCAK256_HASH_BYTESIZE]; + bool to_feed; if (path_struct == NULL) { return false; @@ -201,9 +206,11 @@ static bool path_depth_list_pop(void) { } path_struct->depth_count -= 1; - finalize_hash_depth(hash); + to_feed = finalize_hash_depth(hash); if (path_struct->depth_count > 0) { - feed_last_hash_depth(hash); + if (to_feed) { + feed_last_hash_depth(hash); + } } else { switch (path_struct->root_type) { case ROOT_DOMAIN: @@ -261,7 +268,7 @@ static bool array_depth_list_pop(void) { return false; } - finalize_hash_depth(hash); + finalize_hash_depth(hash); // return value not checked on purpose feed_last_hash_depth(hash); path_struct->array_depth_count -= 1; @@ -307,7 +314,10 @@ static bool path_update(void) { } feed_last_hash_depth(hash); - ui_712_queue_struct_to_review(); + // TODO: Find a better way to show inner structs in verbose mode when it might be + // an empty array of structs in which case we don't want to show it but the + // size is only known later + // ui_712_queue_struct_to_review(); path_depth_list_push(); } return true; @@ -421,6 +431,8 @@ bool path_new_array_depth(const uint8_t *const data, uint8_t length) { uint8_t total_count = 0; uint8_t pidx; bool is_custom; + uint8_t array_size; + uint8_t array_depth_count_bak; if (path_struct == NULL) { apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; @@ -430,6 +442,8 @@ bool path_new_array_depth(const uint8_t *const data, uint8_t length) { return false; } + array_size = *data; + array_depth_count_bak = path_struct->array_depth_count; for (pidx = 0; pidx < path_struct->depth_count; ++pidx) { if ((field_ptr = get_nth_field(NULL, pidx + 1)) == NULL) { apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; @@ -442,7 +456,7 @@ bool path_new_array_depth(const uint8_t *const data, uint8_t length) { } total_count += depth_count; if (total_count > path_struct->array_depth_count) { - if (!check_and_add_array_depth(depth, total_count, pidx, *data)) { + if (!check_and_add_array_depth(depth, total_count, pidx, array_size)) { return false; } break; @@ -463,9 +477,18 @@ bool path_new_array_depth(const uint8_t *const data, uint8_t length) { cx_sha3_t *hash_ctx = get_last_hash_ctx(); cx_sha3_t *old_ctx = hash_ctx - 1; - memcpy(hash_ctx, old_ctx, sizeof(*old_ctx)); + if (array_size > 0) { + memcpy(hash_ctx, old_ctx, sizeof(*old_ctx)); + } else { + cx_keccak_init(hash_ctx, 256); + } cx_keccak_init(old_ctx, 256); // init hash } + if (array_size == 0) { + do { + path_advance(); + } while (path_struct->array_depth_count != array_depth_count_bak); + } return true; } @@ -515,7 +538,7 @@ static bool path_advance_in_array(void) { if ((path_struct->array_depth_count > 0) && (arr_depth->path_index == (path_struct->depth_count - 1))) { - arr_depth->size -= 1; + if (arr_depth->size > 0) arr_depth->size -= 1; if (arr_depth->size == 0) { array_depth_list_pop(); end_reached = true; diff --git a/src_features/signMessageEIP712_common/common_712.c b/src_features/signMessageEIP712_common/common_712.c index abc1fd509..084a528bb 100644 --- a/src_features/signMessageEIP712_common/common_712.c +++ b/src_features/signMessageEIP712_common/common_712.c @@ -7,7 +7,7 @@ static const uint8_t EIP_712_MAGIC[] = {0x19, 0x01}; -unsigned int ui_712_approve_cb() { +unsigned int ui_712_approve_cb(void) { uint8_t privateKeyData[INT256_LENGTH]; uint8_t hash[INT256_LENGTH]; uint8_t signature[100]; @@ -75,7 +75,7 @@ unsigned int ui_712_approve_cb() { return 0; // do not redraw the widget } -unsigned int ui_712_reject_cb() { +unsigned int ui_712_reject_cb(void) { reset_app_context(); G_io_apdu_buffer[0] = 0x69; G_io_apdu_buffer[1] = 0x85; diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index 199ccbbe0..a107439f5 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -136,6 +136,7 @@ customStatus_e customProcessor(txContext_t *context) { } dataContext.tokenContext.fieldIndex++; dataContext.tokenContext.fieldOffset = 0; + memset(dataContext.tokenContext.data, 0, sizeof(dataContext.tokenContext.data)); return CUSTOM_HANDLED; } @@ -195,7 +196,8 @@ static void address_to_string(uint8_t *in, } static void raw_fee_to_string(uint256_t *rawFee, char *displayBuffer, uint32_t displayBufferSize) { - const char *feeTicker = get_network_ticker(); + uint64_t chain_id = get_tx_chain_id(); + const char *feeTicker = get_displayable_ticker(&chain_id); uint8_t tickerOffset = 0; uint32_t i; @@ -262,10 +264,10 @@ static void nonce_to_string(const txInt256_t *nonce, char *out, size_t out_size) } static void get_network_as_string(char *out, size_t out_size) { - const char *name = get_network_name(); + uint64_t chain_id = get_tx_chain_id(); + const char *name = get_network_name_from_chain_id(&chain_id); if (name == NULL) { // No network name found so simply copy the chain ID as the network name. - uint64_t chain_id = get_chain_id(); u64_to_string(chain_id, out, out_size); } else { // Network name found, simply copy it. @@ -312,13 +314,14 @@ static int strcasecmp_workaround(const char *str1, const char *str2) { void finalizeParsing(bool direct) { char displayBuffer[50]; uint8_t decimals = WEI_TO_ETHER; - const char *ticker = get_network_ticker(); + uint64_t chain_id = get_tx_chain_id(); + const char *ticker = get_displayable_ticker(&chain_id); ethPluginFinalize_t pluginFinalize; bool use_standard_UI = true; // Verify the chain if (chainConfig->chainId != ETHEREUM_MAINNET_CHAINID) { - uint64_t id = get_chain_id(); + uint64_t id = get_tx_chain_id(); if (chainConfig->chainId != id) { PRINTF("Invalid chainID %u expected %u\n", id, chainConfig->chainId); @@ -423,8 +426,8 @@ void finalizeParsing(bool direct) { } // User has just validated a swap but ETH received apdus about a non standard plugin / contract - if (called_from_swap && !use_standard_UI) { - PRINTF("ERR_SILENT_MODE_CHECK_FAILED, called_from_swap\n"); + if (G_called_from_swap && !use_standard_UI) { + PRINTF("ERR_SILENT_MODE_CHECK_FAILED, G_called_from_swap\n"); THROW(ERR_SILENT_MODE_CHECK_FAILED); } @@ -446,7 +449,7 @@ void finalizeParsing(bool direct) { sizeof(displayBuffer), &global_sha3, chainConfig->chainId); - if (called_from_swap) { + if (G_called_from_swap) { // Ensure the values are the same that the ones that have been previously validated if (strcasecmp_workaround(strings.common.fullAddress, displayBuffer) != 0) { PRINTF("ERR_SILENT_MODE_CHECK_FAILED, address check failed\n"); @@ -465,7 +468,7 @@ void finalizeParsing(bool direct) { ticker, displayBuffer, sizeof(displayBuffer)); - if (called_from_swap) { + if (G_called_from_swap) { // Ensure the values are the same that the ones that have been previously validated if (strcmp(strings.common.fullAmount, displayBuffer) != 0) { PRINTF("ERR_SILENT_MODE_CHECK_FAILED, amount check failed\n"); @@ -483,7 +486,7 @@ void finalizeParsing(bool direct) { &tmpContent.txContent.startgas, displayBuffer, sizeof(displayBuffer)); - if (called_from_swap) { + if (G_called_from_swap) { // Ensure the values are the same that the ones that have been previously validated if (strcmp(strings.common.maxFee, displayBuffer) != 0) { PRINTF("ERR_SILENT_MODE_CHECK_FAILED, fees check failed\n"); @@ -509,7 +512,7 @@ void finalizeParsing(bool direct) { // If called from swap, the user as already validated a standard transaction // We have already checked the fields of this transaction above - no_consent_check = called_from_swap && use_standard_UI; + no_consent_check = G_called_from_swap && use_standard_UI; #ifdef NO_CONSENT no_consent_check = true; diff --git a/src_features/signTx/ui_common_signTx.c b/src_features/signTx/ui_common_signTx.c index ef8171f25..e57bb2125 100644 --- a/src_features/signTx/ui_common_signTx.c +++ b/src_features/signTx/ui_common_signTx.c @@ -2,12 +2,14 @@ #include "shared_context.h" #include "utils.h" #include "common_ui.h" +#include "handle_swap_sign_transaction.h" unsigned int io_seproxyhal_touch_tx_ok(__attribute__((unused)) const bagl_element_t *e) { uint8_t privateKeyData[INT256_LENGTH]; uint8_t signature[100]; cx_ecfp_private_key_t privateKey; uint32_t tx = 0; + int err; io_seproxyhal_io_heartbeat(); os_perso_derive_node_bip32(CX_CURVE_256K1, tmpCtx.transactionContext.bip32.path, @@ -59,10 +61,19 @@ unsigned int io_seproxyhal_touch_tx_ok(__attribute__((unused)) const bagl_elemen tx = 65; G_io_apdu_buffer[tx++] = 0x90; G_io_apdu_buffer[tx++] = 0x00; + // Send back the response, do not restart the event loop - io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx); - if (called_from_swap) { - os_sched_exit(0); + err = io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx); + if (G_called_from_swap) { + PRINTF("G_called_from_swap\n"); + + // If we are in swap mode and have validated a TX, we send it and immediately quit + if (err == 0) { + finalize_exchange_sign_transaction(true); + } else { + PRINTF("Unrecoverable\n"); + os_sched_exit(-1); + } } reset_app_context(); // Display back the original UX diff --git a/src_nbgl/ui_approve_tx.c b/src_nbgl/ui_approve_tx.c new file mode 100644 index 000000000..a6253c35d --- /dev/null +++ b/src_nbgl/ui_approve_tx.c @@ -0,0 +1,306 @@ +#include +#include +#include "shared_context.h" +#include "ui_callbacks.h" +#include "ui_nbgl.h" +#include "ethUtils.h" +#include "ui_signing.h" +#include "plugins.h" +#include "domain_name.h" + +#define TEXT_TX "transaction" +// 1 more than actually displayed on screen, because of calculations in StaticReview +#define MAX_PLUGIN_ITEMS_PER_SCREEN 4 +#define TAG_MAX_LEN 43 +#define VALUE_MAX_LEN 79 +enum { + REJECT_TOKEN, + START_REVIEW_TOKEN, +}; + +static nbgl_layoutTagValue_t pair; +// these buffers are used as circular +static char title_buffer[MAX_PLUGIN_ITEMS_PER_SCREEN][TAG_MAX_LEN]; +static char msg_buffer[MAX_PLUGIN_ITEMS_PER_SCREEN][VALUE_MAX_LEN]; +static nbgl_layoutTagValueList_t useCaseTagValueList; +static nbgl_pageInfoLongPress_t infoLongPress; + +struct tx_approval_context_t { + bool fromPlugin; + bool blindSigning; + bool displayNetwork; +#ifdef HAVE_DOMAIN_NAME + bool domain_name_match; +#endif +}; + +static struct tx_approval_context_t tx_approval_context; + +static void reviewContinueCommon(void); + +static void reviewReject(void) { + io_seproxyhal_touch_tx_cancel(NULL); + memset(&tx_approval_context, 0, sizeof(tx_approval_context)); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_tx_ok(NULL); + memset(&tx_approval_context, 0, sizeof(tx_approval_context)); +} + +static void onConfirmAbandon(void) { + nbgl_useCaseStatus("Transaction rejected", false, reviewReject); +} + +static void rejectTransactionQuestion(void) { + nbgl_useCaseConfirm(REJECT_QUESTION(TEXT_TX), + NULL, + REJECT_CONFIRM_BUTTON, + RESUME(TEXT_TX), + onConfirmAbandon); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + nbgl_useCaseStatus("TRANSACTION\nSIGNED", true, confirmTransation); + } else { + rejectTransactionQuestion(); + } +} + +// called by NBGL to get the tag/value pair corresponding to pairIndex +static nbgl_layoutTagValue_t *getTagValuePair(uint8_t pairIndex) { + static int counter = 0; + + if (tx_approval_context.fromPlugin) { + if (pairIndex < dataContext.tokenContext.pluginUiMaxItems) { + // for the next dataContext.tokenContext.pluginUiMaxItems items, get tag/value from + // plugin_ui_get_item_internal() + dataContext.tokenContext.pluginUiCurrentItem = pairIndex; + plugin_ui_get_item_internal((uint8_t *) title_buffer[counter], + TAG_MAX_LEN, + (uint8_t *) msg_buffer[counter], + VALUE_MAX_LEN); + pair.item = title_buffer[counter]; + pair.value = msg_buffer[counter]; + } else { + pairIndex -= dataContext.tokenContext.pluginUiMaxItems; + // for the last 1 (or 2), tags are fixed + if (tx_approval_context.displayNetwork && (pairIndex == 0)) { + pair.item = "Network"; + pair.value = strings.common.network_name; + } else { + pair.item = "Max fees"; + pair.value = strings.common.maxFee; + } + } + } else { + uint8_t target_index = 0; + + if (pairIndex == target_index++) { + pair.item = "Amount"; + pair.value = strings.common.fullAmount; + } +#ifdef HAVE_DOMAIN_NAME + if (tx_approval_context.domain_name_match) { + if (pairIndex == target_index++) { + pair.item = "Domain"; + pair.value = g_domain_name; + } + } + if (!tx_approval_context.domain_name_match || N_storage.verbose_domain_name) { +#endif // HAVE_DOMAIN_NAME + if (pairIndex == target_index++) { + pair.item = "Address"; + pair.value = strings.common.fullAddress; + } +#ifdef HAVE_DOMAIN_NAME + } +#endif // HAVE_DOMAIN_NAME + if (N_storage.displayNonce) { + if (pairIndex == target_index++) { + pair.item = "Nonce"; + pair.value = strings.common.nonce; + } + } + if (pairIndex == target_index++) { + pair.item = "Max fees"; + pair.value = strings.common.maxFee; + } + if (pairIndex == target_index++) { + pair.item = "Network"; + pair.value = strings.common.network_name; + } + } + // counter is used as index to circular buffer + counter++; + if (counter == MAX_PLUGIN_ITEMS_PER_SCREEN) { + counter = 0; + } + return &pair; +} + +static void pageCallback(int token, uint8_t index) { + (void) index; + nbgl_pageRelease(pageContext); + if (token == REJECT_TOKEN) { + reviewReject(); + } else if (token == START_REVIEW_TOKEN) { + reviewContinueCommon(); + } +} + +static void reviewContinue(void) { + if (tx_approval_context.blindSigning) { + nbgl_pageInfoDescription_t info = { + .centeredInfo.icon = &C_round_warning_64px, + .centeredInfo.text1 = "Blind Signing", + .centeredInfo.text2 = + "This transaction cannot be\nsecurely interpreted by Ledger\nStax. It might put " + "your assets\nat risk.", + .centeredInfo.text3 = NULL, + .centeredInfo.style = LARGE_CASE_INFO, + .centeredInfo.offsetY = -32, + .footerText = REJECT(TEXT_TX), + .footerToken = REJECT_TOKEN, + .tapActionText = "Tap to continue", + .tapActionToken = START_REVIEW_TOKEN, + .topRightStyle = NO_BUTTON_STYLE, + .actionButtonText = NULL, + .tuneId = TUNE_TAP_CASUAL}; + + if (pageContext != NULL) { + nbgl_pageRelease(pageContext); + pageContext = NULL; + } + pageContext = nbgl_pageDrawInfo(&pageCallback, NULL, &info); + } else { + reviewContinueCommon(); + } +} + +static const nbgl_icon_details_t *get_tx_icon(void) { + const nbgl_icon_details_t *icon = NULL; + + if (tx_approval_context.fromPlugin && (pluginType == EXTERNAL)) { + if (caller_app && caller_app->name) { + if ((strlen(strings.common.fullAddress) == strlen(caller_app->name)) && + (strcmp(strings.common.fullAddress, caller_app->name) == 0)) { + icon = get_app_icon(true); + } + } + } else { + icon = get_app_icon(false); + } + return icon; +} + +static void reviewContinueCommon(void) { + uint8_t nbPairs = 0; + + if (tx_approval_context.fromPlugin) { + // plugin id + max items + fees + nbPairs += dataContext.tokenContext.pluginUiMaxItems + 1; + } else { + nbPairs += 3; + if (N_storage.displayNonce) { + nbPairs++; + } +#ifdef HAVE_DOMAIN_NAME + uint64_t chain_id = get_tx_chain_id(); + tx_approval_context.domain_name_match = + has_domain_name(&chain_id, tmpContent.txContent.destination); + if (tx_approval_context.domain_name_match && N_storage.verbose_domain_name) { + nbPairs += 1; + } +#endif // HAVE_DOMAIN_NAME + } + + if (tx_approval_context.displayNetwork) { + nbPairs++; + } + + useCaseTagValueList.pairs = NULL; + useCaseTagValueList.callback = getTagValuePair; + useCaseTagValueList.startIndex = 0; + useCaseTagValueList.nbPairs = nbPairs; ///< number of pairs in pairs array + useCaseTagValueList.smallCaseForValue = false; + useCaseTagValueList.wrapping = false; + infoLongPress.icon = get_tx_icon(); + infoLongPress.text = tx_approval_context.fromPlugin ? g_stax_shared_buffer : SIGN(TEXT_TX); + infoLongPress.longPressText = SIGN_BUTTON; + nbgl_useCaseStaticReview(&useCaseTagValueList, &infoLongPress, REJECT(TEXT_TX), reviewChoice); +} + +// Replace "Review" by "Sign" and add questionmark +static void prepare_sign_text(void) { + uint8_t sign_length = strlen("Sign"); + uint8_t review_length = strlen("Review"); + + memmove(g_stax_shared_buffer, "Sign", sign_length); + memmove(g_stax_shared_buffer + sign_length, + g_stax_shared_buffer + review_length, + strlen(g_stax_shared_buffer) - review_length + 1); + strlcat(g_stax_shared_buffer, "?", sizeof(g_stax_shared_buffer)); +} + +// Force operation to be lowercase +static void get_lowercase_operation(char *dst, size_t dst_len) { + const char *src = strings.common.fullAmount; + size_t idx; + + for (idx = 0; (idx < dst_len - 1) && (src[idx] != '\0'); ++idx) { + dst[idx] = (char) tolower((int) src[idx]); + } + dst[idx] = '\0'; +} + +static void buildFirstPage(void) { + if (tx_approval_context.fromPlugin) { + char op_name[sizeof(strings.common.fullAmount)]; + plugin_ui_get_id(); + + get_lowercase_operation(op_name, sizeof(op_name)); + if (pluginType == EXTERNAL) { + snprintf(g_stax_shared_buffer, + sizeof(g_stax_shared_buffer), + "Review transaction\nto %s\non %s", + op_name, + strings.common.fullAddress); + } else { + snprintf(g_stax_shared_buffer, + sizeof(g_stax_shared_buffer), + "Review transaction\nto %s\n%s", + op_name, + strings.common.fullAddress); + } + nbgl_useCaseReviewStart(get_tx_icon(), + g_stax_shared_buffer, + NULL, + REJECT(TEXT_TX), + reviewContinue, + rejectTransactionQuestion); + prepare_sign_text(); + } else { + nbgl_useCaseReviewStart(get_tx_icon(), + REVIEW(TEXT_TX), + NULL, + REJECT(TEXT_TX), + reviewContinue, + rejectTransactionQuestion); + } +} + +void ux_approve_tx(bool fromPlugin) { + tx_approval_context.blindSigning = + !fromPlugin && tmpContent.txContent.dataPresent && !N_storage.contractDetails; + tx_approval_context.fromPlugin = fromPlugin; + tx_approval_context.displayNetwork = false; + + uint64_t chain_id = get_tx_chain_id(); + if (chainConfig->chainId == ETHEREUM_MAINNET_CHAINID && chain_id != chainConfig->chainId) { + tx_approval_context.displayNetwork = true; + } + + buildFirstPage(); +} diff --git a/src_nbgl/ui_confirm_parameter_selector.c b/src_nbgl/ui_confirm_parameter_selector.c new file mode 100644 index 000000000..80418e18c --- /dev/null +++ b/src_nbgl/ui_confirm_parameter_selector.c @@ -0,0 +1,83 @@ +#include "common_ui.h" +#include "ui_signing.h" +#include "ui_nbgl.h" +#include "network.h" + +typedef enum { PARAMETER_CONFIRMATION, SELECTOR_CONFIRMATION } e_confirmation_type; + +static nbgl_layoutTagValue_t pair; +static e_confirmation_type confirm_type; + +static void reviewReject(void) { + io_seproxyhal_touch_data_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_data_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + confirmTransation(); + } else { + reviewReject(); + } +} + +static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { + if (page == 0) { + pair.item = (confirm_type == PARAMETER_CONFIRMATION) ? "Parameter" : "Selector"; + pair.value = strings.tmp.tmp; + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 1; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) &pair; + } else if (page == 1) { + snprintf(g_stax_shared_buffer, + sizeof(g_stax_shared_buffer), + "Confirm %s", + (confirm_type == PARAMETER_CONFIRMATION) ? "parameter" : "selector"); + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(true); + content->infoLongPress.text = g_stax_shared_buffer; + content->infoLongPress.longPressText = "Hold to confirm"; + } else { + return false; + } + // valid page so return true + return true; +} + +static void reviewContinue(void) { + snprintf(g_stax_shared_buffer, + sizeof(g_stax_shared_buffer), + "Reject %s", + (confirm_type == PARAMETER_CONFIRMATION) ? "parameter" : "selector"); + nbgl_useCaseRegularReview(0, + 2, + g_stax_shared_buffer, + NULL, + displayTransactionPage, + reviewChoice); +} + +static void buildScreen(void) { + snprintf(g_stax_shared_buffer, + sizeof(g_stax_shared_buffer), + "Verify %s", + (confirm_type == PARAMETER_CONFIRMATION) ? "parameter" : "selector"); + nbgl_useCaseReviewStart(get_app_icon(true), + g_stax_shared_buffer, + NULL, + REJECT_BUTTON, + reviewContinue, + reviewReject); +} + +void ui_confirm_parameter(void) { + confirm_type = PARAMETER_CONFIRMATION; + buildScreen(); +} + +void ui_confirm_selector(void) { + confirm_type = SELECTOR_CONFIRMATION; + buildScreen(); +} diff --git a/src_nbgl/ui_display_privacy.c b/src_nbgl/ui_display_privacy.c new file mode 100644 index 000000000..2b08175c9 --- /dev/null +++ b/src_nbgl/ui_display_privacy.c @@ -0,0 +1,69 @@ +#include "common_ui.h" +#include "ui_signing.h" +#include "ui_nbgl.h" +#include "ui_callbacks.h" +#include "nbgl_use_case.h" +#include "network.h" + +static nbgl_layoutTagValue_t pairs[2]; +static char *review_string; + +static void reviewReject(void) { + io_seproxyhal_touch_privacy_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_privacy_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + confirmTransation(); + } else { + reviewReject(); + } +} + +static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { + if (page == 0) { + pairs[0].item = "Address"; + pairs[0].value = strings.common.fullAddress; + pairs[1].item = "Key"; + pairs[1].value = strings.common.fullAmount; + + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 2; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) pairs; + } else if (page == 1) { + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(true); + content->infoLongPress.text = review_string; + content->infoLongPress.longPressText = "Hold to approve"; + } else { + return false; + } + // valid page so return true + return true; +} + +static void reviewContinue(void) { + nbgl_useCaseRegularReview(0, 2, REJECT_BUTTON, NULL, displayTransactionPage, reviewChoice); +} + +static void buildFirstPage(void) { + nbgl_useCaseReviewStart(get_app_icon(true), + review_string, + NULL, + REJECT_BUTTON, + reviewContinue, + reviewReject); +} + +void ui_display_privacy_public_key(void) { + review_string = (char *) "Provide public\nprivacy key"; + buildFirstPage(); +} + +void ui_display_privacy_shared_secret(void) { + review_string = (char *) "Provide public\nsecret key"; + buildFirstPage(); +} diff --git a/src_nbgl/ui_get_eth2_public_key.c b/src_nbgl/ui_get_eth2_public_key.c new file mode 100644 index 000000000..9f388df27 --- /dev/null +++ b/src_nbgl/ui_get_eth2_public_key.c @@ -0,0 +1,30 @@ +#include +#include "shared_context.h" +#include "ui_callbacks.h" +#include "ui_nbgl.h" + +static void reviewReject(void) { + io_seproxyhal_touch_address_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_address_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + // display a status page and go back to main + nbgl_useCaseStatus("ADDRESS\nVERIFIED", true, confirmTransation); + } else { + nbgl_useCaseStatus("Address verification\ncancelled", false, reviewReject); + } +} + +static void buildScreen(void) { + snprintf(strings.tmp.tmp, 100, "0x%.*H", 48, tmpCtx.publicKeyContext.publicKey.W); + nbgl_useCaseAddressConfirmation(strings.tmp.tmp, reviewChoice); +} + +void ui_display_public_eth2(void) { + buildScreen(); +} \ No newline at end of file diff --git a/src_nbgl/ui_get_public_key.c b/src_nbgl/ui_get_public_key.c new file mode 100644 index 000000000..5966737ea --- /dev/null +++ b/src_nbgl/ui_get_public_key.c @@ -0,0 +1,28 @@ +#include +#include "shared_context.h" +#include "ui_callbacks.h" +#include "ui_nbgl.h" + +static void reviewReject(void) { + io_seproxyhal_touch_address_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_address_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + // display a status page and go back to main + nbgl_useCaseStatus("ADDRESS\nVERIFIED", true, confirmTransation); + } else { + nbgl_useCaseStatus("Address verification\ncancelled", false, reviewReject); + } +} + +static void buildScreen(void) { + nbgl_useCaseAddressConfirmation(strings.common.fullAddress, reviewChoice); +} +void ui_display_public_key(void) { + buildScreen(); +} \ No newline at end of file diff --git a/src_nbgl/ui_get_stark_public_key.c b/src_nbgl/ui_get_stark_public_key.c new file mode 100644 index 000000000..ce5778750 --- /dev/null +++ b/src_nbgl/ui_get_stark_public_key.c @@ -0,0 +1,29 @@ +#include +#include "shared_context.h" +#include "ui_callbacks.h" +#include "ui_nbgl.h" + +static void reviewReject(void) { + io_seproxyhal_touch_address_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_stark_pubkey_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + // display a status page and go back to main + nbgl_useCaseStatus("ADDRESS\nVERIFIED", true, confirmTransation); + } else { + nbgl_useCaseStatus("Address verification\ncancelled", false, reviewReject); + } +} + +static void buildScreen(void) { + nbgl_useCaseAddressConfirmation(strings.tmp.tmp, reviewChoice); +} + +void ui_display_stark_public(void) { + buildScreen(); +} \ No newline at end of file diff --git a/src_nbgl/ui_idle.c b/src_nbgl/ui_idle.c new file mode 100644 index 000000000..faa47ca99 --- /dev/null +++ b/src_nbgl/ui_idle.c @@ -0,0 +1,63 @@ +#include "common_ui.h" +#include "shared_context.h" +#include "ui_nbgl.h" +#include "nbgl_use_case.h" +#include "glyphs.h" +#include "network.h" + +char g_stax_shared_buffer[SHARED_BUFFER_SIZE] = {0}; +nbgl_page_t *pageContext; + +#define FORMAT_PLUGIN "This app enables clear\nsigning transactions for\nthe %s dApp." + +void releaseContext(void) { + if (pageContext != NULL) { + nbgl_pageRelease(pageContext); + pageContext = NULL; + } +} + +void app_quit(void) { + // exit app here + os_sched_exit(-1); +} + +const nbgl_icon_details_t *get_app_icon(bool caller_icon) { + const nbgl_icon_details_t *icon = NULL; + + if (caller_icon && caller_app) { + if (caller_app->icon) { + icon = caller_app->icon; + } + } else { + icon = &ICONGLYPH; + } + if (icon == NULL) { + PRINTF("%s(%s) returned NULL!\n", __func__, (caller_icon ? "true" : "false")); + } + return icon; +} + +void ui_idle(void) { + const char *app_name = NULL; + const char *tagline = NULL; + + if (caller_app) { + app_name = caller_app->name; + + if (caller_app->type == CALLER_TYPE_PLUGIN) { + snprintf(g_stax_shared_buffer, sizeof(g_stax_shared_buffer), FORMAT_PLUGIN, app_name); + tagline = g_stax_shared_buffer; + } + } else { // Ethereum app + uint64_t mainnet_chain_id = ETHEREUM_MAINNET_CHAINID; + app_name = get_network_name_from_chain_id(&mainnet_chain_id); + } + + nbgl_useCaseHome((char *) app_name, + get_app_icon(true), + tagline, + true, + ui_menu_settings, + app_quit); +} diff --git a/src_nbgl/ui_message_signing.c b/src_nbgl/ui_message_signing.c new file mode 100644 index 000000000..51e1a7ec2 --- /dev/null +++ b/src_nbgl/ui_message_signing.c @@ -0,0 +1,50 @@ +#include "ui_nbgl.h" +#include "ui_signing.h" +#include "ui_logic.h" +#include "ui_message_signing.h" +#include "glyphs.h" + +static void (*g_approved_func)(void) = NULL; +static void (*g_rejected_func)(void) = NULL; + +static void ui_message_rejection_handler() { + nbgl_useCaseStatus("Message signing\ncancelled", false, g_rejected_func); +} + +static void ui_message_confirm_rejection(void) { + nbgl_useCaseConfirm(REJECT_QUESTION(TEXT_MESSAGE), + NULL, + REJECT_CONFIRM_BUTTON, + RESUME(TEXT_MESSAGE), + ui_message_rejection_handler); +} + +void ui_message_review_choice(bool confirm) { + if (confirm) { + nbgl_useCaseStatus("MESSAGE\nSIGNED", true, g_approved_func); + } else { + ui_message_confirm_rejection(); + } +} + +void ui_message_start(const char *title, + void (*start_func)(void), + void (*approved_func)(void), + void (*rejected_func)(void)) { + g_approved_func = approved_func; + g_rejected_func = rejected_func; + nbgl_useCaseReviewStart(&C_Message_64px, + title, + NULL, + REJECT_BUTTON, + start_func, + ui_message_confirm_rejection); +} + +void ui_message_712_approved(void) { + ui_712_approve(); +} + +void ui_message_712_rejected(void) { + ui_712_reject(); +} diff --git a/src_nbgl/ui_message_signing.h b/src_nbgl/ui_message_signing.h new file mode 100644 index 000000000..008f57400 --- /dev/null +++ b/src_nbgl/ui_message_signing.h @@ -0,0 +1,20 @@ +#ifndef UI_MESSAGE_SIGNING_H_ +#define UI_MESSAGE_SIGNING_H_ + +#include + +#define TEXT_MESSAGE "message" +#define TEXT_TYPED_MESSAGE "typed " TEXT_MESSAGE +#define TEXT_REVIEW_EIP712 REVIEW(TEXT_TYPED_MESSAGE) +#define TEXT_SIGN_EIP712 SIGN(TEXT_TYPED_MESSAGE) + +void ui_message_review_choice(bool confirm); +void ui_message_start(const char *title, + void (*start_func)(void), + void (*approved_func)(void), + void (*rejected_func)(void)); + +void ui_message_712_approved(void); +void ui_message_712_rejected(void); + +#endif // UI_MESSAGE_SIGNING_H_ diff --git a/src_nbgl/ui_nbgl.h b/src_nbgl/ui_nbgl.h new file mode 100644 index 000000000..921d604d9 --- /dev/null +++ b/src_nbgl/ui_nbgl.h @@ -0,0 +1,21 @@ +#ifndef _UI_NBGL_H_ +#define _UI_NBGL_H_ + +#include +#include +#include + +#define SHARED_BUFFER_SIZE SHARED_CTX_FIELD_1_SIZE +extern char g_stax_shared_buffer[SHARED_BUFFER_SIZE]; + +extern nbgl_page_t* pageContext; + +void releaseContext(void); + +const nbgl_icon_details_t* get_app_icon(bool caller_icon); + +void ui_idle(void); +void ui_menu_settings(void); +void ui_menu_about(void); + +#endif // _UI_NBGL_H_ diff --git a/src_nbgl/ui_settings.c b/src_nbgl/ui_settings.c new file mode 100644 index 000000000..9d3656cc9 --- /dev/null +++ b/src_nbgl/ui_settings.c @@ -0,0 +1,132 @@ +#include "common_ui.h" +#include "ui_nbgl.h" +#include "nbgl_use_case.h" + +static const char* const infoTypes[] = {"Version", APPNAME " App"}; +static const char* const infoContents[] = {APPVERSION, "(c) " BUILD_YEAR " Ledger"}; + +enum { + BLIND_SIGNING_TOKEN = FIRST_USER_TOKEN, + DEBUG_TOKEN, + NONCE_TOKEN, +#ifdef HAVE_EIP712_FULL_SUPPORT + EIP712_VERBOSE_TOKEN, +#endif // HAVE_EIP712_FULL_SUPPORT +#ifdef HAVE_DOMAIN_NAME + DOMAIN_NAME_VERBOSE_TOKEN +#endif // HAVE_DOMAIN_NAME +}; + +static nbgl_layoutSwitch_t switches[3]; + +static bool navCallback(uint8_t page, nbgl_pageContent_t* content) { + uint8_t index = 0; + + switch (page) { + case 0: + content->type = INFOS_LIST; + content->infosList.nbInfos = 2; + content->infosList.infoTypes = (const char**) infoTypes; + content->infosList.infoContents = (const char**) infoContents; + break; + + case 1: + switches[index++] = + (nbgl_layoutSwitch_t){.initState = N_storage.dataAllowed ? ON_STATE : OFF_STATE, + .text = "Blind signing", + .subText = "Enable transaction blind\nsigning", + .token = BLIND_SIGNING_TOKEN, + .tuneId = TUNE_TAP_CASUAL}; + switches[index++] = + (nbgl_layoutSwitch_t){.initState = N_storage.contractDetails ? ON_STATE : OFF_STATE, + .text = "Debug", + .subText = "Display contract data\ndetails", + .token = DEBUG_TOKEN, + .tuneId = TUNE_TAP_CASUAL}; + switches[index++] = + (nbgl_layoutSwitch_t){.initState = N_storage.displayNonce ? ON_STATE : OFF_STATE, + .text = "Nonce", + .subText = "Display account nonce\nin transaction", + .token = NONCE_TOKEN, + .tuneId = TUNE_TAP_CASUAL}; + + content->type = SWITCHES_LIST; + content->switchesList.nbSwitches = index; + content->switchesList.switches = (nbgl_layoutSwitch_t*) switches; + break; + + case 2: +#ifdef HAVE_EIP712_FULL_SUPPORT + switches[index++] = + (nbgl_layoutSwitch_t){.initState = N_storage.verbose_eip712 ? ON_STATE : OFF_STATE, + .text = "Verbose EIP712", + .subText = "Ignore filtering and\ndisplay raw content", + .token = EIP712_VERBOSE_TOKEN, + .tuneId = TUNE_TAP_CASUAL}; +#endif // HAVE_EIP712_FULL_SUPPORT +#ifdef HAVE_DOMAIN_NAME + switches[index++] = (nbgl_layoutSwitch_t){ + .initState = N_storage.verbose_domain_name ? ON_STATE : OFF_STATE, + .text = "Verbose domains", + .subText = "Show resolved address", + .token = DOMAIN_NAME_VERBOSE_TOKEN, + .tuneId = TUNE_TAP_CASUAL}; +#endif // HAVE_DOMAIN_NAME + + content->type = SWITCHES_LIST; + content->switchesList.nbSwitches = index; + content->switchesList.switches = (nbgl_layoutSwitch_t*) switches; + break; + + default: + return false; + break; + } + + return true; +} + +static void controlsCallback(int token, uint8_t index) { + (void) index; + uint8_t value; + switch (token) { + case BLIND_SIGNING_TOKEN: + value = (N_storage.dataAllowed ? 0 : 1); + nvm_write((void*) &N_storage.dataAllowed, (void*) &value, sizeof(uint8_t)); + break; + case DEBUG_TOKEN: + value = (N_storage.contractDetails ? 0 : 1); + nvm_write((void*) &N_storage.contractDetails, (void*) &value, sizeof(uint8_t)); + break; + case NONCE_TOKEN: + value = (N_storage.displayNonce ? 0 : 1); + nvm_write((void*) &N_storage.displayNonce, (void*) &value, sizeof(uint8_t)); + break; +#ifdef HAVE_EIP712_FULL_SUPPORT + case EIP712_VERBOSE_TOKEN: + value = (N_storage.verbose_eip712 ? 0 : 1); + nvm_write((void*) &N_storage.verbose_eip712, (void*) &value, sizeof(uint8_t)); + break; +#endif // HAVE_EIP712_FULL_SUPPORT +#ifdef HAVE_DOMAIN_NAME + case DOMAIN_NAME_VERBOSE_TOKEN: + value = (N_storage.verbose_domain_name ? 0 : 1); + nvm_write((void*) &N_storage.verbose_domain_name, (void*) &value, sizeof(uint8_t)); + break; +#endif // HAVE_DOMAIN_NAME + } +} + +void ui_menu_settings(void) { + uint8_t nb_screens = 2; +#if defined(HAVE_EIP712_FULL_SUPPORT) || defined(HAVE_DOMAIN_NAME) + nb_screens += 1; +#endif + nbgl_useCaseSettings(APPNAME " settings", + 0, + nb_screens, + false, + ui_idle, + navCallback, + controlsCallback); +} diff --git a/src_nbgl/ui_sign_712.c b/src_nbgl/ui_sign_712.c new file mode 100644 index 000000000..4d9aae7a3 --- /dev/null +++ b/src_nbgl/ui_sign_712.c @@ -0,0 +1,87 @@ +#ifdef HAVE_EIP712_FULL_SUPPORT + +#include "common_ui.h" +#include "ui_nbgl.h" +#include "ui_logic.h" +#include "common_712.h" +#include "nbgl_use_case.h" +#include "network.h" +#include "ui_message_signing.h" +#include "ui_signing.h" + +static nbgl_layoutTagValue_t pair; + +static bool display_sign_page(uint8_t page, nbgl_pageContent_t *content) { + (void) page; + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(true); + content->infoLongPress.text = TEXT_SIGN_EIP712; + content->infoLongPress.longPressText = SIGN_BUTTON; + return true; +} + +static bool display_review_page(uint8_t page, nbgl_pageContent_t *content) { + bool ret; + uint16_t len; + + switch (page) { + case 0: + // limit the value to one page + nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_MEDIUM_32px, + strings.tmp.tmp, + SCREEN_WIDTH - (2 * BORDER_MARGIN), + NB_MAX_LINES_IN_REVIEW, + &len); + strings.tmp.tmp[len] = '\0'; + + pair.item = strings.tmp.tmp2; + pair.value = strings.tmp.tmp; + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 1; + content->tagValueList.pairs = &pair; + content->tagValueList.wrapping = false; + ret = true; + break; + + case 1: + switch (ui_712_next_field()) { + case EIP712_NO_MORE_FIELD: + ui_712_switch_to_sign(); + ret = true; + break; + case EIP712_FIELD_INCOMING: + case EIP712_FIELD_LATER: + default: + break; + } + __attribute__((fallthrough)); + + default: + ret = false; + break; + } + return ret; +} + +static void handle_display(nbgl_navCallback_t cb) { + nbgl_useCaseRegularReview(0, 0, REJECT_BUTTON, NULL, cb, ui_message_review_choice); +} + +void ui_712_start(void) { + g_position = UI_SIGNING_POSITION_START; + ui_message_start(TEXT_REVIEW_EIP712, + &ui_712_switch_to_message, + &ui_message_712_approved, + &ui_message_712_rejected); +} + +void ui_712_switch_to_message(void) { + g_position = UI_SIGNING_POSITION_REVIEW; + handle_display(display_review_page); +} + +void ui_712_switch_to_sign(void) { + g_position = UI_SIGNING_POSITION_SIGN; + handle_display(display_sign_page); +} + +#endif // HAVE_EIP712_FULL_SUPPORT diff --git a/src_nbgl/ui_sign_712_v0.c b/src_nbgl/ui_sign_712_v0.c new file mode 100644 index 000000000..ec38eeaf7 --- /dev/null +++ b/src_nbgl/ui_sign_712_v0.c @@ -0,0 +1,78 @@ +#include "common_ui.h" +#include "ui_nbgl.h" +#include "common_712.h" +#include "network.h" +#include "ethUtils.h" +#include "ui_message_signing.h" +#include "ui_signing.h" + +static nbgl_layoutTagValue_t pairs[2]; + +static void start_review(void); // forward declaration + +static char *format_hash(const uint8_t *hash, char *buffer, size_t buffer_size, size_t offset) { + snprintf(buffer + offset, buffer_size - offset, "0x%.*H", KECCAK256_HASH_BYTESIZE, hash); + return buffer + offset; +} + +static bool display_review_page(uint8_t page, nbgl_pageContent_t *content) { + if (page == 0) { + pairs[0].item = "Domain hash"; + pairs[0].value = format_hash(tmpCtx.messageSigningContext712.domainHash, + strings.tmp.tmp, + sizeof(strings.tmp.tmp), + 0); + pairs[1].item = "Message hash"; + pairs[1].value = format_hash(tmpCtx.messageSigningContext712.messageHash, + strings.tmp.tmp, + sizeof(strings.tmp.tmp), + 70); + + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 2; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) pairs; + } else if (page == 1) { + g_position = UI_SIGNING_POSITION_SIGN; + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(true); + content->infoLongPress.text = TEXT_SIGN_EIP712; + content->infoLongPress.longPressText = SIGN_BUTTON; + } else { + return false; + } + // valid page so return true + return true; +} + +static void display_review(void) { + uint8_t page; + + switch (g_position) { + case UI_SIGNING_POSITION_REVIEW: + page = 0; + break; + case UI_SIGNING_POSITION_SIGN: + page = 1; + break; + default: + return; // should not happen + } + nbgl_useCaseRegularReview(page, + 2, + REJECT_BUTTON, + NULL, + display_review_page, + ui_message_review_choice); +} + +static void start_review(void) { + g_position = UI_SIGNING_POSITION_REVIEW; + display_review(); +} + +void ui_sign_712_v0(void) { + g_position = UI_SIGNING_POSITION_START; + ui_message_start(TEXT_REVIEW_EIP712, + &start_review, + &ui_message_712_approved, + &ui_message_712_rejected); +} diff --git a/src_nbgl/ui_sign_message.c b/src_nbgl/ui_sign_message.c new file mode 100644 index 000000000..6d85f80e8 --- /dev/null +++ b/src_nbgl/ui_sign_message.c @@ -0,0 +1,154 @@ +#include +#include "shared_context.h" +#include "ui_callbacks.h" +#include "ui_nbgl.h" +#include "sign_message.h" +#include "glyphs.h" +#include "nbgl_use_case.h" +#include "common_ui.h" +#include "ui_message_signing.h" +#include "ui_signing.h" + +#define TEXT_REVIEW_EIP191 REVIEW(TEXT_MESSAGE) +#define TEXT_SIGN_EIP191 SIGN(TEXT_MESSAGE) + +typedef enum { + UI_191_ACTION_IDLE = 0, + UI_191_ACTION_ADVANCE_IN_MESSAGE, + UI_191_ACTION_GO_TO_SIGN +} e_ui_191_action; + +static e_ui_191_action g_action; + +static bool skip_message; + +static nbgl_layoutTagValue_t pair; + +static uint32_t eip191MessageIdx = 0; +static uint32_t stringsTmpTmpIdx = 0; + +static void reject_message(void) { + io_seproxyhal_touch_signMessage_cancel(); +} + +static void sign_message(void) { + io_seproxyhal_touch_signMessage_ok(); +} + +static bool display_message(nbgl_pageContent_t *content) { + uint16_t len = 0; + bool reached; + + if (g_action == UI_191_ACTION_ADVANCE_IN_MESSAGE) { + strncpy(g_stax_shared_buffer + eip191MessageIdx, + strings.tmp.tmp + stringsTmpTmpIdx, + SHARED_BUFFER_SIZE - eip191MessageIdx); + reached = nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_MEDIUM_32px, + (char *) g_stax_shared_buffer, + SCREEN_WIDTH - (2 * BORDER_MARGIN), + NB_MAX_LINES_IN_REVIEW, + &len); + + stringsTmpTmpIdx = len - eip191MessageIdx; + eip191MessageIdx = len; + g_stax_shared_buffer[eip191MessageIdx] = '\0'; + + if (!reached && eip191MessageIdx < SHARED_BUFFER_SIZE) { + stringsTmpTmpIdx = 0; + question_switcher(); + + if (g_action != UI_191_ACTION_GO_TO_SIGN) { + return false; + } + } else if (reached || eip191MessageIdx == SHARED_BUFFER_SIZE) { + eip191MessageIdx = 0; + } + } + + pair.value = g_stax_shared_buffer; + pair.item = "Message"; + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 1; + content->tagValueList.pairs = &pair; + content->tagValueList.smallCaseForValue = false; + content->tagValueList.nbMaxLinesForValue = NB_MAX_LINES_IN_REVIEW; + content->tagValueList.wrapping = false; + + if ((g_action != UI_191_ACTION_IDLE) && (stringsTmpTmpIdx >= strlen(strings.tmp.tmp))) { + // Fetch the next content to display into strings.tmp.tmp buffer. + stringsTmpTmpIdx = 0; + question_switcher(); + } + return true; +} + +static bool display_sign(nbgl_pageContent_t *content) { + bool ret = false; + + if (g_position != UI_SIGNING_POSITION_SIGN) { + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = &C_Message_64px; + content->infoLongPress.text = TEXT_SIGN_EIP191; + content->infoLongPress.longPressText = SIGN_BUTTON; + g_position = UI_SIGNING_POSITION_SIGN; + ret = true; + } + return ret; +} + +static bool nav_callback(uint8_t page, nbgl_pageContent_t *content) { + bool ret = true; + + if (page == LAST_PAGE_FOR_REVIEW) { // was skipped + skip_message = true; + skip_rest_of_message(); + } + if ((g_action != UI_191_ACTION_GO_TO_SIGN) && (g_position != UI_SIGNING_POSITION_SIGN)) { + if (skip_message) { + // do not refresh when this callback triggers after user validation + ret = false; + } else { + ret = display_message(content); + } + } else { + // the last page must contain a long press button + ret = display_sign(content); + } + return ret; +} + +static void continue_review(void) { + nbgl_useCaseForwardOnlyReview(REJECT_BUTTON, NULL, nav_callback, ui_message_review_choice); +} + +void ui_191_start(void) { + g_position = UI_SIGNING_POSITION_START; + + skip_message = false; + eip191MessageIdx = 0; + stringsTmpTmpIdx = 0; + + ui_message_start(TEXT_REVIEW_EIP191, &ui_191_switch_to_message, &sign_message, &reject_message); +} + +void ui_191_switch_to_message(void) { + g_position = UI_SIGNING_POSITION_REVIEW; + g_action = UI_191_ACTION_ADVANCE_IN_MESSAGE; + // No question mechanism on Stax: + // Message is already displayed + continue_review(); +} + +void ui_191_switch_to_sign(void) { + g_action = UI_191_ACTION_GO_TO_SIGN; + // Next nav_callback callback must display + // the hold to approve screen + if (skip_message) { + continue_review(); // to force screen refresh + } +} + +void ui_191_switch_to_question(void) { + // No question mechanism on Stax: + // Always display the next message chunk. + continue_displaying_message(); +} diff --git a/src_nbgl/ui_signing.c b/src_nbgl/ui_signing.c new file mode 100644 index 000000000..2becdf07d --- /dev/null +++ b/src_nbgl/ui_signing.c @@ -0,0 +1,3 @@ +#include "ui_signing.h" + +e_ui_signing_position g_position; diff --git a/src_nbgl/ui_signing.h b/src_nbgl/ui_signing.h new file mode 100644 index 000000000..e7b8f71a2 --- /dev/null +++ b/src_nbgl/ui_signing.h @@ -0,0 +1,21 @@ +#ifndef UI_SIGNING_H_ +#define UI_SIGNING_H_ + +#define SIGN_BUTTON "Hold to sign" +#define REJECT_BUTTON "Reject" +#define SIGN(msg) "Sign " msg "?" +#define REVIEW(msg) "Review " msg +#define REJECT(msg) "Reject " msg +#define REJECT_QUESTION(msg) REJECT(msg) "?" +#define REJECT_CONFIRM_BUTTON "Yes, reject" +#define RESUME(msg) "Go back to " msg + +typedef enum { + UI_SIGNING_POSITION_START = 0, + UI_SIGNING_POSITION_REVIEW, + UI_SIGNING_POSITION_SIGN +} e_ui_signing_position; + +extern e_ui_signing_position g_position; + +#endif // UI_SIGNING_H_ diff --git a/src_nbgl/ui_stark_limit_order.c b/src_nbgl/ui_stark_limit_order.c new file mode 100644 index 000000000..89cfdbf83 --- /dev/null +++ b/src_nbgl/ui_stark_limit_order.c @@ -0,0 +1,68 @@ +#include "common_ui.h" +#include "ui_signing.h" +#include "ui_nbgl.h" +#include "ui_callbacks.h" +#include "nbgl_use_case.h" +#include "network.h" + +#ifdef HAVE_STARKWARE + +static nbgl_layoutTagValue_t pairs[3]; + +static void reviewReject(void) { + io_seproxyhal_touch_tx_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_stark_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + confirmTransation(); + } else { + reviewReject(); + } +} + +static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { + if (page == 0) { + pairs[0].item = "Sell"; + pairs[0].value = strings.common.fullAmount; + pairs[1].item = "Buy"; + pairs[1].value = strings.common.maxFee; + pairs[2].item = "Token Account"; + pairs[2].value = strings.common.fullAddress; + + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 3; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) pairs; + } else if (page == 1) { + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(false); + content->infoLongPress.text = "Review stark limit order"; + content->infoLongPress.longPressText = SIGN_BUTTON; + } else { + return false; + } + // valid page so return true + return true; +} + +static void reviewContinue(void) { + nbgl_useCaseRegularReview(0, 2, REJECT_BUTTON, NULL, displayTransactionPage, reviewChoice); +} + +static void buildFirstPage(void) { + nbgl_useCaseReviewStart(get_app_icon(false), + "Review stark limit order", + NULL, + REJECT_BUTTON, + reviewContinue, + reviewReject); +} + +void ui_stark_limit_order(void) { + buildFirstPage(); +} + +#endif diff --git a/src_nbgl/ui_stark_transfer.c b/src_nbgl/ui_stark_transfer.c new file mode 100644 index 000000000..d7decfbca --- /dev/null +++ b/src_nbgl/ui_stark_transfer.c @@ -0,0 +1,133 @@ +#include +#include "shared_context.h" +#include "ui_callbacks.h" +#include "ui_nbgl.h" +#include "ui_signing.h" +#include "starkDisplayUtils.h" +#include "ethUtils.h" +#include "network.h" + +#ifdef HAVE_STARKWARE + +static nbgl_layoutTagValue_t pairs[3]; +static char condAddressBuffer[43]; +struct stark_transfer_context { + bool selfTransfer; + bool conditional; +}; + +static struct stark_transfer_context context; + +static void reviewReject(void) { + io_seproxyhal_touch_tx_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_stark_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + confirmTransation(); + } else { + reviewReject(); + } +} + +static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { + uint8_t count = 0; + if (page == 0) { + pairs[count].item = "Amount"; + pairs[count].value = tmpContent.tmp; + count++; + + if (context.selfTransfer == false && context.conditional == false) { + pairs[count].item = "Master Account"; + pairs[count].value = strings.tmp.tmp; + count++; + } + if (context.conditional) { + stark_sign_display_master_account(); + pairs[count].item = "Master Account"; + pairs[count].value = strings.tmp.tmp; + count++; + } + + pairs[count].item = "Token Account"; + pairs[count].value = strings.tmp.tmp2; + count++; + + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = count; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) pairs; + + return true; + } + if (page == 1) { + if (context.conditional) { + getEthDisplayableAddress(dataContext.starkContext.conditionAddress, + condAddressBuffer, + sizeof(condAddressBuffer), + &global_sha3, + chainConfig->chainId); + pairs[0].item = "Cond. Address"; + pairs[0].value = condAddressBuffer; + + stark_sign_display_condition_fact(); + pairs[1].item = "Cond. Address"; + pairs[1].value = strings.tmp.tmp; + + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 2; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) pairs; + + return true; + } else { + page++; + } + } + if (page == 2) { + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(false); + content->infoLongPress.text = "Review transaction"; + content->infoLongPress.longPressText = SIGN_BUTTON; + return true; + } + + return false; +} + +static void reviewContinue(void) { + nbgl_useCaseRegularReview(0, + context.conditional ? 3 : 2, + REJECT_BUTTON, + NULL, + displayTransactionPage, + reviewChoice); +} + +void ui_stark_transfer(bool selfTransfer, bool conditional) { + context.selfTransfer = selfTransfer; + context.conditional = conditional; + char *subTitle; + if (conditional) { + if (selfTransfer) { + subTitle = (char *) "Conditional Self Transfer"; + } else { + subTitle = (char *) "Conditional Transfer"; + } + } else { + if (selfTransfer) { + subTitle = (char *) "Self Transfer"; + } else { + subTitle = (char *) "Transfer"; + } + } + nbgl_useCaseReviewStart(get_app_icon(false), + "Review stark\ntransaction", + subTitle, + REJECT_BUTTON, + reviewContinue, + reviewReject); +} + +#endif // #ifdef HAVE_STARKWARE diff --git a/src_nbgl/ui_stark_unsafe_sign.c b/src_nbgl/ui_stark_unsafe_sign.c new file mode 100644 index 000000000..45a8556db --- /dev/null +++ b/src_nbgl/ui_stark_unsafe_sign.c @@ -0,0 +1,70 @@ +#include "common_ui.h" +#include "ui_signing.h" +#include "ui_nbgl.h" +#include "ui_callbacks.h" +#include "nbgl_use_case.h" +#include "network.h" + +#ifdef HAVE_STARKWARE + +static nbgl_layoutTagValue_t pairs[2]; +static char from_account[64]; +static char message_hash[64]; + +static void reviewReject(void) { + io_seproxyhal_touch_tx_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_stark_unsafe_sign_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + confirmTransation(); + } else { + reviewReject(); + } +} + +static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { + snprintf(from_account, sizeof(from_account), "0x%.*H", 32, dataContext.starkContext.w1); + snprintf(message_hash, sizeof(message_hash), "0x%.*H", 32, dataContext.starkContext.w2); + + if (page == 0) { + pairs[0].item = "From Account"; + pairs[0].value = from_account; + pairs[1].item = "Hash"; + pairs[1].value = message_hash; + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 2; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) pairs; + } else if (page == 1) { + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(false); + content->infoLongPress.text = "Unsafe Stark Sign"; + content->infoLongPress.longPressText = SIGN_BUTTON; + } else { + return false; + } + // valid page so return true + return true; +} + +static void reviewContinue(void) { + nbgl_useCaseRegularReview(0, 2, REJECT_BUTTON, NULL, displayTransactionPage, reviewChoice); +} + +static void buildFirstPage(void) { + nbgl_useCaseReviewStart(get_app_icon(false), + "Unsafe Stark Sign", + NULL, + REJECT_BUTTON, + reviewContinue, + reviewReject); +} + +void ui_stark_unsafe_sign(void) { + buildFirstPage(); +} + +#endif // HAVE_STARKWARE diff --git a/src_nbgl/ui_warning_contract_data.c b/src_nbgl/ui_warning_contract_data.c new file mode 100644 index 000000000..2619dce4e --- /dev/null +++ b/src_nbgl/ui_warning_contract_data.c @@ -0,0 +1,21 @@ +#include +#include "shared_context.h" +#include "ui_callbacks.h" +#include "ui_nbgl.h" + +static void ui_warning_contract_data_choice(bool confirm) { + if (confirm) { + ui_idle(); + } else { + ui_menu_settings(); + } +} + +void ui_warning_contract_data(void) { + nbgl_useCaseChoice(&C_warning64px, + "This message cannot\nbe clear-signed", + "Enable blind-signing in\nthe settings to sign\nthis transaction.", + "Exit", + "Go to settings", + ui_warning_contract_data_choice); +} diff --git a/src_plugins/erc20/erc20_plugin.c b/src_plugins/erc20/erc20_plugin.c index 04062d82e..220e05f9d 100644 --- a/src_plugins/erc20/erc20_plugin.c +++ b/src_plugins/erc20/erc20_plugin.c @@ -182,7 +182,11 @@ void erc20_plugin_call(int message, void *parameters) { case ETH_PLUGIN_QUERY_CONTRACT_ID: { ethQueryContractID_t *msg = (ethQueryContractID_t *) parameters; +#ifdef HAVE_NBGL + strlcpy(msg->name, "ERC20 token", msg->nameLength); +#else strlcpy(msg->name, "Type", msg->nameLength); +#endif strlcpy(msg->version, "Approve", msg->versionLength); msg->result = ETH_PLUGIN_RESULT_OK; } break; diff --git a/src_plugins/eth2/eth2_plugin.c b/src_plugins/eth2/eth2_plugin.c index 29ea29947..c93c82ec6 100644 --- a/src_plugins/eth2/eth2_plugin.c +++ b/src_plugins/eth2/eth2_plugin.c @@ -212,7 +212,7 @@ void eth2_plugin_call(int message, void *parameters) { strlcpy(msg->title, "Validator", msg->titleLength); strlcpy(msg->msg, context->deposit_address, msg->msgLength); msg->result = ETH_PLUGIN_RESULT_OK; - } + } break; default: break; } diff --git a/tests/ragger/app/client.py b/tests/ragger/app/client.py index 9732c81a6..616670c0a 100644 --- a/tests/ragger/app/client.py +++ b/tests/ragger/app/client.py @@ -2,14 +2,9 @@ from typing import Optional from ragger.backend import BackendInterface from ragger.utils import RAPDU -from ragger.navigator import NavInsID, NavIns, NanoNavigator -from .command_builder import EthereumCmdBuilder -from .setting import SettingType, SettingImpl +from .command_builder import CommandBuilder from .eip712 import EIP712FieldType -from .response_parser import EthereumRespParser from .tlv import format_tlv -import signal -import time from pathlib import Path import keychain import rlp @@ -41,58 +36,19 @@ class DOMAIN_NAME_TAG(IntEnum): ADDRESS = 0x22 -class EthereumClient: - _settings: dict[SettingType, SettingImpl] = { - SettingType.BLIND_SIGNING: SettingImpl( - [ "nanos", "nanox", "nanosp" ] - ), - SettingType.DEBUG_DATA: SettingImpl( - [ "nanos", "nanox", "nanosp" ] - ), - SettingType.NONCE: SettingImpl( - [ "nanos", "nanox", "nanosp" ] - ), - SettingType.VERBOSE_EIP712: SettingImpl( - [ "nanox", "nanosp" ] - ), - SettingType.VERBOSE_ENS: SettingImpl( - [ "nanox", "nanosp" ] - ) - } - _click_delay = 1/4 - _eip712_filtering = False - - def __init__(self, client: BackendInterface, golden_run: bool): +class EthAppClient: + def __init__(self, client: BackendInterface): self._client = client - self._chain_id = 1 - self._cmd_builder = EthereumCmdBuilder() - self._resp_parser = EthereumRespParser() - self._nav = NanoNavigator(client, client.firmware, golden_run) - signal.signal(signal.SIGALRM, self._click_signal_timeout) - for setting in self._settings.values(): - setting.value = False + self._cmd_builder = CommandBuilder() def _send(self, payload: bytearray): return self._client.exchange_async_raw(payload) - def _recv(self) -> RAPDU: + def response(self) -> RAPDU: return self._client._last_async_response - def _click_signal_timeout(self, _signum: int, _frame): - self._client.right_click() - - def _enable_click_until_response(self): - signal.setitimer(signal.ITIMER_REAL, - self._click_delay, - self._click_delay) - - def _disable_click_until_response(self): - signal.setitimer(signal.ITIMER_REAL, 0, 0) - def eip712_send_struct_def_struct_name(self, name: str): - with self._send(self._cmd_builder.eip712_send_struct_def_struct_name(name)): - pass - return self._recv().status == 0x9000 + return self._send(self._cmd_builder.eip712_send_struct_def_struct_name(name)) def eip712_send_struct_def_struct_field(self, field_type: EIP712FieldType, @@ -100,98 +56,45 @@ def eip712_send_struct_def_struct_field(self, type_size: int, array_levels: [], key_name: str): - with self._send(self._cmd_builder.eip712_send_struct_def_struct_field( - field_type, - type_name, - type_size, - array_levels, - key_name)): - pass - return self._recv() + return self._send(self._cmd_builder.eip712_send_struct_def_struct_field( + field_type, + type_name, + type_size, + array_levels, + key_name)) def eip712_send_struct_impl_root_struct(self, name: str): - with self._send(self._cmd_builder.eip712_send_struct_impl_root_struct(name)): - self._enable_click_until_response() - self._disable_click_until_response() - return self._recv() + return self._send(self._cmd_builder.eip712_send_struct_impl_root_struct(name)) def eip712_send_struct_impl_array(self, size: int): - with self._send(self._cmd_builder.eip712_send_struct_impl_array(size)): - pass - return self._recv() + return self._send(self._cmd_builder.eip712_send_struct_impl_array(size)) def eip712_send_struct_impl_struct_field(self, raw_value: bytes): - for apdu in self._cmd_builder.eip712_send_struct_impl_struct_field(raw_value): - with self._send(apdu): - self._enable_click_until_response() - self._disable_click_until_response() - assert self._recv().status == 0x9000 - - def eip712_sign_new(self, bip32_path: str): - with self._send(self._cmd_builder.eip712_sign_new(bip32_path)): - time.sleep(0.5) # tight on timing, needed by the CI otherwise might fail sometimes - if not self._settings[SettingType.VERBOSE_EIP712].value and \ - not self._eip712_filtering: # need to skip the message hash - self._client.right_click() - self._client.right_click() - self._client.both_click() # approve signature - resp = self._recv() - assert resp.status == 0x9000 - return self._resp_parser.sign(resp.data) + chunks = self._cmd_builder.eip712_send_struct_impl_struct_field(raw_value) + for chunk in chunks[:-1]: + with self._send(chunk): + pass + return self._send(chunks[-1]) + + def eip712_sign_new(self, bip32_path: str, verbose: bool): + return self._send(self._cmd_builder.eip712_sign_new(bip32_path)) def eip712_sign_legacy(self, bip32_path: str, domain_hash: bytes, message_hash: bytes): - with self._send(self._cmd_builder.eip712_sign_legacy(bip32_path, - domain_hash, - message_hash)): - self._client.right_click() # sign typed message screen - for _ in range(2): # two hashes (domain + message) - if self._client.firmware.device == "nanos": - screens_per_hash = 4 - else: - screens_per_hash = 2 - for _ in range(screens_per_hash): - self._client.right_click() - self._client.both_click() # approve signature - - resp = self._recv() - - assert resp.status == 0x9000 - return self._resp_parser.sign(resp.data) - - def settings_set(self, new_values: dict[SettingType, bool]): - # Go to settings - for _ in range(2): - self._client.right_click() - self._client.both_click() - - for enum in self._settings.keys(): - if self._client.firmware.device in self._settings[enum].devices: - if enum in new_values.keys(): - if new_values[enum] != self._settings[enum].value: - self._client.both_click() - self._settings[enum].value = new_values[enum] - self._client.right_click() - self._client.both_click() + return self._send(self._cmd_builder.eip712_sign_legacy(bip32_path, + domain_hash, + message_hash)) def eip712_filtering_activate(self): - with self._send(self._cmd_builder.eip712_filtering_activate()): - pass - self._eip712_filtering = True - assert self._recv().status == 0x9000 + return self._send(self._cmd_builder.eip712_filtering_activate()) def eip712_filtering_message_info(self, name: str, filters_count: int, sig: bytes): - with self._send(self._cmd_builder.eip712_filtering_message_info(name, filters_count, sig)): - self._enable_click_until_response() - self._disable_click_until_response() - assert self._recv().status == 0x9000 + return self._send(self._cmd_builder.eip712_filtering_message_info(name, filters_count, sig)) def eip712_filtering_show_field(self, name: str, sig: bytes): - with self._send(self._cmd_builder.eip712_filtering_show_field(name, sig)): - pass - assert self._recv().status == 0x9000 + return self._send(self._cmd_builder.eip712_filtering_show_field(name, sig)) def send_fund(self, bip32_path: str, @@ -200,8 +103,7 @@ def send_fund(self, gas_limit: int, to: bytes, amount: float, - chain_id: int, - screenshot_collection: str = None): + chain_id: int): data = list() data.append(nonce) data.append(gas_price) @@ -213,27 +115,14 @@ def send_fund(self, data.append(bytes()) data.append(bytes()) - for chunk in self._cmd_builder.sign(bip32_path, rlp.encode(data)): + chunks = self._cmd_builder.sign(bip32_path, rlp.encode(data)) + for chunk in chunks[:-1]: with self._send(chunk): - nav_ins = NavIns(NavInsID.RIGHT_CLICK) - final_ins = [ NavIns(NavInsID.BOTH_CLICK) ] - target_text = "and send" - if screenshot_collection: - self._nav.navigate_until_text_and_compare(nav_ins, - final_ins, - target_text, - ROOT_SCREENSHOT_PATH, - screenshot_collection) - else: - self._nav.navigate_until_text(nav_ins, - final_ins, - target_text) - - def get_challenge(self) -> int: - with self._send(self._cmd_builder.get_challenge()): - pass - resp = self._recv() - return self._resp_parser.challenge(resp.data) + pass + return self._send(chunks[-1]) + + def get_challenge(self): + return self._send(self._cmd_builder.get_challenge()) def provide_domain_name(self, challenge: int, name: str, addr: bytes): payload = format_tlv(DOMAIN_NAME_TAG.STRUCTURE_TYPE, 3) # TrustedDomainName @@ -247,6 +136,8 @@ def provide_domain_name(self, challenge: int, name: str, addr: bytes): payload += format_tlv(DOMAIN_NAME_TAG.SIGNATURE, keychain.sign_data(keychain.Key.DOMAIN_NAME, payload)) - for chunk in self._cmd_builder.provide_domain_name(payload): + chunks = self._cmd_builder.provide_domain_name(payload) + for chunk in chunks[:-1]: with self._send(chunk): pass + return self._send(chunks[-1]) diff --git a/tests/ragger/app/command_builder.py b/tests/ragger/app/command_builder.py index aac10d014..ae3f730f8 100644 --- a/tests/ragger/app/command_builder.py +++ b/tests/ragger/app/command_builder.py @@ -29,7 +29,7 @@ class P2Type(IntEnum): FILTERING_CONTRACT_NAME = 0x0f FILTERING_FIELD_NAME = 0xff -class EthereumCmdBuilder: +class CommandBuilder: _CLA: int = 0xE0 def _serialize(self, @@ -103,6 +103,7 @@ def eip712_send_struct_impl_array(self, size: int) -> bytes: data) def eip712_send_struct_impl_struct_field(self, data: bytearray) -> Iterator[bytes]: + chunks = list() # Add a 16-bit integer with the data's byte length (network byte order) data_w_length = bytearray() data_w_length.append((len(data) & 0xff00) >> 8) @@ -110,11 +111,12 @@ def eip712_send_struct_impl_struct_field(self, data: bytearray) -> Iterator[byte data_w_length += data while len(data_w_length) > 0: p1 = P1Type.PARTIAL_SEND if len(data_w_length) > 0xff else P1Type.COMPLETE_SEND - yield self._serialize(InsType.EIP712_SEND_STRUCT_IMPL, - p1, - P2Type.STRUCT_FIELD, - data_w_length[:0xff]) + chunks.append(self._serialize(InsType.EIP712_SEND_STRUCT_IMPL, + p1, + P2Type.STRUCT_FIELD, + data_w_length[:0xff])) data_w_length = data_w_length[0xff:] + return chunks def eip712_sign_new(self, bip32_path: str) -> bytes: data = pack_derivation_path(bip32_path) @@ -167,29 +169,33 @@ def eip712_filtering_show_field(self, name: str, sig: bytes) -> bytes: P2Type.FILTERING_FIELD_NAME, self._eip712_filtering_send_name(name, sig)) - def sign(self, bip32_path: str, rlp_data: bytes) -> Iterator[bytes]: + def sign(self, bip32_path: str, rlp_data: bytes) -> list[bytes]: + apdus = list() payload = pack_derivation_path(bip32_path) payload += rlp_data p1 = P1Type.SIGN_FIRST_CHUNK while len(payload) > 0: - yield self._serialize(InsType.SIGN, - p1, - 0x00, - payload[:0xff]) + apdus.append(self._serialize(InsType.SIGN, + p1, + 0x00, + payload[:0xff])) payload = payload[0xff:] p1 = P1Type.SIGN_SUBSQT_CHUNK + return apdus def get_challenge(self) -> bytes: return self._serialize(InsType.GET_CHALLENGE, 0x00, 0x00) - def provide_domain_name(self, tlv_payload: bytes) -> bytes: + def provide_domain_name(self, tlv_payload: bytes) -> list[bytes]: + chunks = list() payload = struct.pack(">H", len(tlv_payload)) payload += tlv_payload p1 = 1 while len(payload) > 0: - yield self._serialize(InsType.PROVIDE_DOMAIN_NAME, - p1, - 0x00, - payload[:0xff]) + chunks.append(self._serialize(InsType.PROVIDE_DOMAIN_NAME, + p1, + 0x00, + payload[:0xff])) payload = payload[0xff:] p1 = 0 + return chunks diff --git a/tests/ragger/app/response_parser.py b/tests/ragger/app/response_parser.py index 242f4cff5..5e73df498 100644 --- a/tests/ragger/app/response_parser.py +++ b/tests/ragger/app/response_parser.py @@ -1,18 +1,14 @@ -class EthereumRespParser: - def sign(self, data: bytes): - assert len(data) == (1 + 32 + 32) +def signature(data: bytes) -> tuple[bytes, bytes, bytes]: + assert len(data) == (1 + 32 + 32) - v = data[0:1] - data = data[1:] + v = data[0:1] + data = data[1:] + r = data[0:32] + data = data[32:] + s = data[0:32] - r = data[0:32] - data = data[32:] + return v, r, s - s = data[0:32] - data = data[32:] - - return v, r, s - - def challenge(self, data: bytes) -> int: - assert len(data) == 4 - return int.from_bytes(data, "big") +def challenge(data: bytes) -> int: + assert len(data) == 4 + return int.from_bytes(data, "big") diff --git a/tests/ragger/app/setting.py b/tests/ragger/app/setting.py deleted file mode 100644 index 7e79da72d..000000000 --- a/tests/ragger/app/setting.py +++ /dev/null @@ -1,16 +0,0 @@ -from enum import IntEnum, auto -from typing import List - -class SettingType(IntEnum): - BLIND_SIGNING = 0, - DEBUG_DATA = auto() - NONCE = auto() - VERBOSE_EIP712 = auto() - VERBOSE_ENS = auto() - -class SettingImpl: - devices: List[str] - value: bool - - def __init__(self, devs: List[str]): - self.devices = devs diff --git a/tests/ragger/app/settings.py b/tests/ragger/app/settings.py new file mode 100644 index 000000000..ec6bf78b4 --- /dev/null +++ b/tests/ragger/app/settings.py @@ -0,0 +1,63 @@ +from enum import Enum, auto +from typing import List +from ragger.firmware import Firmware +from ragger.navigator import Navigator, NavInsID, NavIns + +class SettingID(Enum): + BLIND_SIGNING = auto() + DEBUG_DATA = auto() + NONCE = auto() + VERBOSE_EIP712 = auto() + VERBOSE_ENS = auto() + +def get_device_settings(device: str) -> list[SettingID]: + if device == "nanos": + return [ + SettingID.BLIND_SIGNING, + SettingID.DEBUG_DATA, + SettingID.NONCE + ] + if (device == "nanox") or (device == "nanosp") or (device == "stax"): + return [ + SettingID.BLIND_SIGNING, + SettingID.DEBUG_DATA, + SettingID.NONCE, + SettingID.VERBOSE_EIP712, + SettingID.VERBOSE_ENS + ] + return [] + +settings_per_page = 3 + +def get_setting_position(device: str, setting: NavInsID) -> tuple[int, int]: + screen_height = 672 # px + header_height = 85 # px + footer_height = 124 # px + usable_height = screen_height - (header_height + footer_height) + setting_height = usable_height // settings_per_page + index_in_page = get_device_settings(device).index(setting) % settings_per_page + return 350, header_height + (setting_height * index_in_page) + (setting_height // 2) + +def settings_toggle(fw: Firmware, nav: Navigator, to_toggle: list[SettingID]): + moves = list() + settings = get_device_settings(fw.device) + # Assume the app is on the home page + if fw.device.startswith("nano"): + moves += [NavInsID.RIGHT_CLICK] * 2 + moves += [NavInsID.BOTH_CLICK] + for setting in settings: + if setting in to_toggle: + moves += [NavInsID.BOTH_CLICK] + moves += [NavInsID.RIGHT_CLICK] + moves += [NavInsID.BOTH_CLICK] # Back + else: + moves += [NavInsID.USE_CASE_HOME_SETTINGS] + moves += [NavInsID.USE_CASE_SETTINGS_NEXT] + for setting in settings: + setting_idx = settings.index(setting) + if (setting_idx > 0) and (setting_idx % settings_per_page) == 0: + moves += [NavInsID.USE_CASE_SETTINGS_NEXT] + if setting in to_toggle: + moves += [NavIns(NavInsID.TOUCH, get_setting_position(fw.device, setting))] + moves += [NavInsID.USE_CASE_SETTINGS_MULTI_PAGE_EXIT] + nav.navigate(moves, screen_change_before_first_instruction=False) diff --git a/tests/ragger/conftest.py b/tests/ragger/conftest.py index 68799b278..6dd6f4ba3 100644 --- a/tests/ragger/conftest.py +++ b/tests/ragger/conftest.py @@ -1,12 +1,4 @@ -import pytest from ragger.conftest import configuration -from ragger.backend import BackendInterface -from app.client import EthereumClient - -# This final fixture will return the properly configured app client, to be used in tests -@pytest.fixture -def app_client(backend: BackendInterface, golden_run: bool) -> EthereumClient: - return EthereumClient(backend, golden_run) # Pull all features from the base ragger conftest using the overridden configuration pytest_plugins = ("ragger.conftest.base_conftest", ) diff --git a/tests/ragger/eip712/InputData.py b/tests/ragger/eip712/InputData.py index 02a96ebd0..6dd647131 100644 --- a/tests/ragger/eip712/InputData.py +++ b/tests/ragger/eip712/InputData.py @@ -4,15 +4,19 @@ import sys import re import hashlib -from app.client import EthereumClient, EIP712FieldType +from app.client import EthAppClient, EIP712FieldType import keychain +from typing import Callable +import signal # global variables -app_client: EthereumClient = None +app_client: EthAppClient = None filtering_paths = None current_path = list() sig_ctx = {} +autonext_handler: Callable = None + @@ -97,11 +101,12 @@ def send_struct_def_field(typename, keyname): type_enum = EIP712FieldType.CUSTOM typesize = None - app_client.eip712_send_struct_def_struct_field(type_enum, - typename, - typesize, - array_lvls, - keyname) + with app_client.eip712_send_struct_def_struct_field(type_enum, + typename, + typesize, + array_lvls, + keyname): + pass return (typename, type_enum, typesize, array_lvls) @@ -191,7 +196,9 @@ def send_struct_impl_field(value, field): if path in filtering_paths.keys(): send_filtering_show_field(filtering_paths[path]) - app_client.eip712_send_struct_impl_struct_field(data) + with app_client.eip712_send_struct_impl_struct_field(data): + enable_autonext() + disable_autonext() @@ -201,7 +208,8 @@ def evaluate_field(structs, data, field, lvls_left, new_level = True): if new_level: current_path.append(field["name"]) if len(array_lvls) > 0 and lvls_left > 0: - app_client.eip712_send_struct_impl_array(len(data)) + with app_client.eip712_send_struct_impl_array(len(data)): + pass idx = 0 for subdata in data: current_path.append("[]") @@ -252,7 +260,9 @@ def send_filtering_message_info(display_name: str, filters_count: int): to_sign.append(ord(char)) sig = keychain.sign_data(keychain.Key.CAL, to_sign) - app_client.eip712_filtering_message_info(display_name, filters_count, sig) + with app_client.eip712_filtering_message_info(display_name, filters_count, sig): + enable_autonext() + disable_autonext() # ledgerjs doesn't actually sign anything, and instead uses already pre-computed signatures def send_filtering_show_field(display_name): @@ -270,7 +280,8 @@ def send_filtering_show_field(display_name): for char in display_name: to_sign.append(ord(char)) sig = keychain.sign_data(keychain.Key.CAL, to_sign) - app_client.eip712_filtering_show_field(display_name, sig) + with app_client.eip712_filtering_show_field(display_name, sig): + pass def read_filtering_file(domain, message, filtering_file_path): data_json = None @@ -309,9 +320,29 @@ def init_signature_context(types, domain): schema_hash = hashlib.sha224(schema_str.encode()) sig_ctx["schema_hash"] = bytearray.fromhex(schema_hash.hexdigest()) -def process_file(aclient: EthereumClient, input_file_path: str, filtering_file_path = None) -> bool: + +def next_timeout(_signum: int, _frame): + autonext_handler() + +def enable_autonext(): + seconds = 1/4 + if app_client._client.firmware.device == 'stax': # Stax Speculos is slow + interval = seconds * 3 + else: + interval = seconds + signal.setitimer(signal.ITIMER_REAL, seconds, interval) + +def disable_autonext(): + signal.setitimer(signal.ITIMER_REAL, 0, 0) + + +def process_file(aclient: EthAppClient, + input_file_path: str, + filtering_file_path = None, + autonext: Callable = None) -> bool: global sig_ctx global app_client + global autonext_handler app_client = aclient with open(input_file_path, "r") as data: @@ -322,23 +353,31 @@ def process_file(aclient: EthereumClient, input_file_path: str, filtering_file_p domain = data_json["domain"] message = data_json["message"] + if autonext: + autonext_handler = autonext + signal.signal(signal.SIGALRM, next_timeout) + if filtering_file_path: init_signature_context(types, domain) filtr = read_filtering_file(domain, message, filtering_file_path) # send types definition for key in types.keys(): - app_client.eip712_send_struct_def_struct_name(key) + with app_client.eip712_send_struct_def_struct_name(key): + pass for f in types[key]: (f["type"], f["enum"], f["typesize"], f["array_lvls"]) = \ send_struct_def_field(f["type"], f["name"]) if filtering_file_path: - app_client.eip712_filtering_activate() + with app_client.eip712_filtering_activate(): + pass prepare_filtering(filtr, message) # send domain implementation - app_client.eip712_send_struct_impl_root_struct(domain_typename) + with app_client.eip712_send_struct_impl_root_struct(domain_typename): + enable_autonext() + disable_autonext() if not send_struct_impl(types, domain, domain_typename): return False @@ -349,7 +388,9 @@ def process_file(aclient: EthereumClient, input_file_path: str, filtering_file_p send_filtering_message_info(domain["name"], len(filtering_paths)) # send message implementation - app_client.eip712_send_struct_impl_root_struct(message_typename) + with app_client.eip712_send_struct_impl_root_struct(message_typename): + enable_autonext() + disable_autonext() if not send_struct_impl(types, message, message_typename): return False diff --git a/tests/ragger/eip712/input_files/13-empty_arrays-data.json b/tests/ragger/eip712/input_files/13-empty_arrays-data.json new file mode 100644 index 000000000..7a1f93943 --- /dev/null +++ b/tests/ragger/eip712/input_files/13-empty_arrays-data.json @@ -0,0 +1,37 @@ +{ + "domain": { + "chainId": 5, + "name": "Empty Arrays", + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", + "version": "1" + }, + "message": { + "list1": [], + "list2": [], + "list3": [ + [ + "1", + "2" + ], + [], + [ + "3", + "4" + ] + ] + }, + "primaryType": "Struct", + "types": { + "EIP712Domain": [ + { "name": "name", "type": "string" }, + { "name": "version", "type": "string" }, + { "name": "chainId", "type": "uint256" }, + { "name": "verifyingContract", "type": "address" } + ], + "Struct": [ + { "name": "list1", "type": "EIP712Domain[]" }, + { "name": "list2", "type": "uint8[]" }, + { "name": "list3", "type": "string[][]" } + ] + } +} diff --git a/tests/ragger/eip712/input_files/13-empty_arrays.ini b/tests/ragger/eip712/input_files/13-empty_arrays.ini new file mode 100644 index 000000000..4784a4884 --- /dev/null +++ b/tests/ragger/eip712/input_files/13-empty_arrays.ini @@ -0,0 +1,4 @@ +[signature] +v = 1b +r = 5d0635a868602e29366da6328f8fadf2d6a9b4e69ee7a65928e85ca56fb1b515 +s = 257364d6faaf5687edf90c3984f4240b0ce7b2dee55aa1f8f39c32d0d4d8c93d diff --git a/tests/ragger/requirements.txt b/tests/ragger/requirements.txt index e408eadea..34213d69f 100644 --- a/tests/ragger/requirements.txt +++ b/tests/ragger/requirements.txt @@ -1,4 +1,4 @@ -ragger[speculos]>=1.6.0,<1.7.0 +ragger[speculos] pytest ecdsa simple-rlp diff --git a/tests/ragger/snapshots/nanosp b/tests/ragger/snapshots/nanosp deleted file mode 120000 index da13a6af4..000000000 --- a/tests/ragger/snapshots/nanosp +++ /dev/null @@ -1 +0,0 @@ -nanox/ \ No newline at end of file diff --git a/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00000.png b/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00000.png new file mode 100644 index 000000000..487ea10fc Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00000.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00001.png b/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00001.png new file mode 100644 index 000000000..f9840e3ab Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00002.png b/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00002.png new file mode 100644 index 000000000..6af0ec54b Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00003.png b/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00003.png new file mode 100644 index 000000000..93112b3ab Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00004.png b/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00004.png new file mode 100644 index 000000000..70c1b9a68 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00005.png b/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00005.png new file mode 100644 index 000000000..570ce28d5 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00005.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00006.png b/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00006.png new file mode 100644 index 000000000..a58590b98 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_non_mainnet/00006.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00000.png b/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00000.png new file mode 100644 index 000000000..487ea10fc Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00000.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00001.png b/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00001.png new file mode 100644 index 000000000..f9840e3ab Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00002.png b/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00002.png new file mode 100644 index 000000000..6a5a9d64a Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00003.png b/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00003.png new file mode 100644 index 000000000..85a797b91 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00004.png b/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00004.png new file mode 100644 index 000000000..70c1b9a68 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00005.png b/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00005.png new file mode 100644 index 000000000..570ce28d5 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00005.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00006.png b/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00006.png new file mode 100644 index 000000000..a58590b98 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_unknown_chain/00006.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00000.png b/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00000.png new file mode 100644 index 000000000..487ea10fc Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00000.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00001.png b/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00001.png new file mode 100644 index 000000000..f9840e3ab Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00002.png b/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00002.png new file mode 100644 index 000000000..6af0ec54b Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00003.png b/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00003.png new file mode 100644 index 000000000..70c1b9a68 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00004.png b/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00004.png new file mode 100644 index 000000000..570ce28d5 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00005.png b/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00005.png new file mode 100644 index 000000000..a58590b98 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_verbose_False/00005.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00000.png b/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00000.png new file mode 100644 index 000000000..487ea10fc Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00000.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00001.png b/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00001.png new file mode 100644 index 000000000..f9840e3ab Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00002.png b/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00002.png new file mode 100644 index 000000000..6af0ec54b Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00003.png b/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00003.png new file mode 100644 index 000000000..6a5a9d64a Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00004.png b/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00004.png new file mode 100644 index 000000000..70c1b9a68 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00005.png b/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00005.png new file mode 100644 index 000000000..570ce28d5 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00005.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00006.png b/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00006.png new file mode 100644 index 000000000..a58590b98 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_verbose_True/00006.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00000.png b/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00000.png new file mode 100644 index 000000000..487ea10fc Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00000.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00001.png b/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00001.png new file mode 100644 index 000000000..f9840e3ab Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00002.png b/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00002.png new file mode 100644 index 000000000..639e4214e Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00003.png b/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00003.png new file mode 100644 index 000000000..70c1b9a68 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00004.png b/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00004.png new file mode 100644 index 000000000..570ce28d5 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00005.png b/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00005.png new file mode 100644 index 000000000..a58590b98 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/domain_name_wrong_addr/00005.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_non_mainnet/00002.png b/tests/ragger/snapshots/nanox/domain_name_non_mainnet/00002.png index 6a5a9d64a..6af0ec54b 100644 Binary files a/tests/ragger/snapshots/nanox/domain_name_non_mainnet/00002.png and b/tests/ragger/snapshots/nanox/domain_name_non_mainnet/00002.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_non_mainnet/00004.png b/tests/ragger/snapshots/nanox/domain_name_non_mainnet/00004.png index 70c1b9a68..1bcb78761 100644 Binary files a/tests/ragger/snapshots/nanox/domain_name_non_mainnet/00004.png and b/tests/ragger/snapshots/nanox/domain_name_non_mainnet/00004.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_non_mainnet/00006.png b/tests/ragger/snapshots/nanox/domain_name_non_mainnet/00006.png index a58590b98..657887225 100644 Binary files a/tests/ragger/snapshots/nanox/domain_name_non_mainnet/00006.png and b/tests/ragger/snapshots/nanox/domain_name_non_mainnet/00006.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00000.png b/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00000.png new file mode 100644 index 000000000..487ea10fc Binary files /dev/null and b/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00000.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00001.png b/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00001.png new file mode 100644 index 000000000..f9840e3ab Binary files /dev/null and b/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00001.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00002.png b/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00002.png new file mode 100644 index 000000000..6a5a9d64a Binary files /dev/null and b/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00002.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00003.png b/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00003.png new file mode 100644 index 000000000..85a797b91 Binary files /dev/null and b/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00003.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00004.png b/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00004.png new file mode 100644 index 000000000..1bcb78761 Binary files /dev/null and b/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00004.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00005.png b/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00005.png new file mode 100644 index 000000000..570ce28d5 Binary files /dev/null and b/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00005.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00006.png b/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00006.png new file mode 100644 index 000000000..657887225 Binary files /dev/null and b/tests/ragger/snapshots/nanox/domain_name_unknown_chain/00006.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_verbose_False/00003.png b/tests/ragger/snapshots/nanox/domain_name_verbose_False/00003.png index 70c1b9a68..1bcb78761 100644 Binary files a/tests/ragger/snapshots/nanox/domain_name_verbose_False/00003.png and b/tests/ragger/snapshots/nanox/domain_name_verbose_False/00003.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_verbose_False/00005.png b/tests/ragger/snapshots/nanox/domain_name_verbose_False/00005.png index a58590b98..657887225 100644 Binary files a/tests/ragger/snapshots/nanox/domain_name_verbose_False/00005.png and b/tests/ragger/snapshots/nanox/domain_name_verbose_False/00005.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_verbose_True/00004.png b/tests/ragger/snapshots/nanox/domain_name_verbose_True/00004.png index 70c1b9a68..1bcb78761 100644 Binary files a/tests/ragger/snapshots/nanox/domain_name_verbose_True/00004.png and b/tests/ragger/snapshots/nanox/domain_name_verbose_True/00004.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_verbose_True/00006.png b/tests/ragger/snapshots/nanox/domain_name_verbose_True/00006.png index a58590b98..657887225 100644 Binary files a/tests/ragger/snapshots/nanox/domain_name_verbose_True/00006.png and b/tests/ragger/snapshots/nanox/domain_name_verbose_True/00006.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_wrong_addr/00003.png b/tests/ragger/snapshots/nanox/domain_name_wrong_addr/00003.png index 70c1b9a68..1bcb78761 100644 Binary files a/tests/ragger/snapshots/nanox/domain_name_wrong_addr/00003.png and b/tests/ragger/snapshots/nanox/domain_name_wrong_addr/00003.png differ diff --git a/tests/ragger/snapshots/nanox/domain_name_wrong_addr/00005.png b/tests/ragger/snapshots/nanox/domain_name_wrong_addr/00005.png index a58590b98..657887225 100644 Binary files a/tests/ragger/snapshots/nanox/domain_name_wrong_addr/00005.png and b/tests/ragger/snapshots/nanox/domain_name_wrong_addr/00005.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_non_mainnet/00000.png b/tests/ragger/snapshots/stax/domain_name_non_mainnet/00000.png new file mode 100644 index 000000000..795ca0c2a Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_non_mainnet/00000.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_non_mainnet/00001.png b/tests/ragger/snapshots/stax/domain_name_non_mainnet/00001.png new file mode 100644 index 000000000..661ea68ef Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_non_mainnet/00001.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_non_mainnet/00002.png b/tests/ragger/snapshots/stax/domain_name_non_mainnet/00002.png new file mode 100644 index 000000000..7f634cc4a Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_non_mainnet/00002.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_non_mainnet/00003.png b/tests/ragger/snapshots/stax/domain_name_non_mainnet/00003.png new file mode 100644 index 000000000..7a05bf7b3 Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_non_mainnet/00003.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_non_mainnet/00004.png b/tests/ragger/snapshots/stax/domain_name_non_mainnet/00004.png new file mode 100644 index 000000000..7a05bf7b3 Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_non_mainnet/00004.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_unknown_chain/00000.png b/tests/ragger/snapshots/stax/domain_name_unknown_chain/00000.png new file mode 100644 index 000000000..795ca0c2a Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_unknown_chain/00000.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_unknown_chain/00001.png b/tests/ragger/snapshots/stax/domain_name_unknown_chain/00001.png new file mode 100644 index 000000000..252785952 Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_unknown_chain/00001.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_unknown_chain/00002.png b/tests/ragger/snapshots/stax/domain_name_unknown_chain/00002.png new file mode 100644 index 000000000..592a8aca7 Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_unknown_chain/00002.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_unknown_chain/00003.png b/tests/ragger/snapshots/stax/domain_name_unknown_chain/00003.png new file mode 100644 index 000000000..299779759 Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_unknown_chain/00003.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_unknown_chain/00004.png b/tests/ragger/snapshots/stax/domain_name_unknown_chain/00004.png new file mode 100644 index 000000000..7a05bf7b3 Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_unknown_chain/00004.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_verbose_False/00000.png b/tests/ragger/snapshots/stax/domain_name_verbose_False/00000.png new file mode 100644 index 000000000..795ca0c2a Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_verbose_False/00000.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_verbose_False/00001.png b/tests/ragger/snapshots/stax/domain_name_verbose_False/00001.png new file mode 100644 index 000000000..5e0c0a941 Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_verbose_False/00001.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_verbose_False/00002.png b/tests/ragger/snapshots/stax/domain_name_verbose_False/00002.png new file mode 100644 index 000000000..7f634cc4a Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_verbose_False/00002.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_verbose_False/00003.png b/tests/ragger/snapshots/stax/domain_name_verbose_False/00003.png new file mode 100644 index 000000000..7a05bf7b3 Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_verbose_False/00003.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_verbose_True/00000.png b/tests/ragger/snapshots/stax/domain_name_verbose_True/00000.png new file mode 100644 index 000000000..795ca0c2a Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_verbose_True/00000.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_verbose_True/00001.png b/tests/ragger/snapshots/stax/domain_name_verbose_True/00001.png new file mode 100644 index 000000000..ad8f07755 Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_verbose_True/00001.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_verbose_True/00002.png b/tests/ragger/snapshots/stax/domain_name_verbose_True/00002.png new file mode 100644 index 000000000..e64dacc0f Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_verbose_True/00002.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_verbose_True/00003.png b/tests/ragger/snapshots/stax/domain_name_verbose_True/00003.png new file mode 100644 index 000000000..299779759 Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_verbose_True/00003.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_verbose_True/00004.png b/tests/ragger/snapshots/stax/domain_name_verbose_True/00004.png new file mode 100644 index 000000000..7a05bf7b3 Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_verbose_True/00004.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_wrong_addr/00000.png b/tests/ragger/snapshots/stax/domain_name_wrong_addr/00000.png new file mode 100644 index 000000000..795ca0c2a Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_wrong_addr/00000.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_wrong_addr/00001.png b/tests/ragger/snapshots/stax/domain_name_wrong_addr/00001.png new file mode 100644 index 000000000..3e505d39d Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_wrong_addr/00001.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_wrong_addr/00002.png b/tests/ragger/snapshots/stax/domain_name_wrong_addr/00002.png new file mode 100644 index 000000000..7f634cc4a Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_wrong_addr/00002.png differ diff --git a/tests/ragger/snapshots/stax/domain_name_wrong_addr/00003.png b/tests/ragger/snapshots/stax/domain_name_wrong_addr/00003.png new file mode 100644 index 000000000..7a05bf7b3 Binary files /dev/null and b/tests/ragger/snapshots/stax/domain_name_wrong_addr/00003.png differ diff --git a/tests/ragger/test_domain_name.py b/tests/ragger/test_domain_name.py index 317f72da4..f137610db 100644 --- a/tests/ragger/test_domain_name.py +++ b/tests/ragger/test_domain_name.py @@ -1,7 +1,11 @@ import pytest from ragger.error import ExceptionRAPDU -from app.client import EthereumClient, StatusWord -from app.setting import SettingType +from ragger.firmware import Firmware +from ragger.backend import BackendInterface +from ragger.navigator import Navigator, NavInsID +from app.client import EthAppClient, StatusWord, ROOT_SCREENSHOT_PATH +from app.settings import SettingID, settings_toggle +import app.response_parser as ResponseParser import struct # Values used across all tests @@ -20,108 +24,211 @@ def verbose(request) -> bool: return request.param -def common(app_client: EthereumClient) -> int: +def common(app_client: EthAppClient) -> int: if app_client._client.firmware.device == "nanos": pytest.skip("Not supported on LNS") - return app_client.get_challenge() + with app_client.get_challenge(): + pass + return ResponseParser.challenge(app_client.response().data) -def test_send_fund(app_client: EthereumClient, verbose: bool): +def test_send_fund(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + test_name: str, + verbose: bool): + app_client = EthAppClient(backend) challenge = common(app_client) if verbose: - app_client.settings_set({ - SettingType.VERBOSE_ENS: True - }) - - app_client.provide_domain_name(challenge, NAME, ADDR) - - app_client.send_fund(BIP32_PATH, - NONCE, - GAS_PRICE, - GAS_LIMIT, - ADDR, - AMOUNT, - CHAIN_ID, - "domain_name_verbose_" + str(verbose)) - -def test_send_fund_wrong_challenge(app_client: EthereumClient): + settings_toggle(firmware, navigator, [SettingID.VERBOSE_ENS]) + + with app_client.provide_domain_name(challenge, NAME, ADDR): + pass + + with app_client.send_fund(BIP32_PATH, + NONCE, + GAS_PRICE, + GAS_LIMIT, + ADDR, + AMOUNT, + CHAIN_ID): + moves = list() + if firmware.device.startswith("nano"): + moves += [ NavInsID.RIGHT_CLICK ] * 4 + if verbose: + moves += [ NavInsID.RIGHT_CLICK ] + moves += [ NavInsID.BOTH_CLICK ] + else: + moves += [ NavInsID.USE_CASE_REVIEW_TAP ] * 2 + if verbose: + moves += [ NavInsID.USE_CASE_REVIEW_TAP ] + moves += [ NavInsID.USE_CASE_REVIEW_CONFIRM ] + navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, + "domain_name_verbose_" + str(verbose), + moves) + + +def test_send_fund_wrong_challenge(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator): + app_client = EthAppClient(backend) caught = False challenge = common(app_client) try: - app_client.provide_domain_name(~challenge & 0xffffffff, NAME, ADDR) + with app_client.provide_domain_name(~challenge & 0xffffffff, NAME, ADDR): + pass except ExceptionRAPDU as e: assert e.status == StatusWord.INVALID_DATA else: assert False # An exception should have been raised -def test_send_fund_wrong_addr(app_client: EthereumClient): + +def test_send_fund_wrong_addr(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + test_name: str): + app_client = EthAppClient(backend) challenge = common(app_client) - app_client.provide_domain_name(challenge, NAME, ADDR) + with app_client.provide_domain_name(challenge, NAME, ADDR): + pass addr = bytearray(ADDR) addr.reverse() - app_client.send_fund(BIP32_PATH, - NONCE, - GAS_PRICE, - GAS_LIMIT, - addr, - AMOUNT, - CHAIN_ID, - "domain_name_wrong_addr") - -def test_send_fund_non_mainnet(app_client: EthereumClient): + with app_client.send_fund(BIP32_PATH, + NONCE, + GAS_PRICE, + GAS_LIMIT, + addr, + AMOUNT, + CHAIN_ID): + moves = list() + if firmware.device.startswith("nano"): + moves += [ NavInsID.RIGHT_CLICK ] * 4 + moves += [ NavInsID.BOTH_CLICK ] + else: + moves += [ NavInsID.USE_CASE_REVIEW_TAP ] * 2 + moves += [ NavInsID.USE_CASE_REVIEW_CONFIRM ] + navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, + "domain_name_wrong_addr", + moves) + + +def test_send_fund_non_mainnet(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + test_name: str): + app_client = EthAppClient(backend) challenge = common(app_client) - app_client.provide_domain_name(challenge, NAME, ADDR) - - app_client.send_fund(BIP32_PATH, - NONCE, - GAS_PRICE, - GAS_LIMIT, - ADDR, - AMOUNT, - 5, - "domain_name_non_mainnet") + with app_client.provide_domain_name(challenge, NAME, ADDR): + pass + + with app_client.send_fund(BIP32_PATH, + NONCE, + GAS_PRICE, + GAS_LIMIT, + ADDR, + AMOUNT, + 5): + moves = list() + if firmware.device.startswith("nano"): + moves += [ NavInsID.RIGHT_CLICK ] * 5 + moves += [ NavInsID.BOTH_CLICK ] + else: + moves += [ NavInsID.USE_CASE_REVIEW_TAP ] * 2 + moves += [ NavInsID.USE_CASE_REVIEW_CONFIRM ] + navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, + "domain_name_non_mainnet", + moves) + + +def test_send_fund_unknown_chain(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + test_name: str): + app_client = EthAppClient(backend) + challenge = common(app_client) -def test_send_fund_domain_too_long(app_client: EthereumClient): + with app_client.provide_domain_name(challenge, NAME, ADDR): + pass + + with app_client.send_fund(BIP32_PATH, + NONCE, + GAS_PRICE, + GAS_LIMIT, + ADDR, + AMOUNT, + 9): + moves = list() + if firmware.device.startswith("nano"): + moves += [ NavInsID.RIGHT_CLICK ] * 5 + moves += [ NavInsID.BOTH_CLICK ] + else: + moves += [ NavInsID.USE_CASE_REVIEW_TAP ] * 3 + moves += [ NavInsID.USE_CASE_REVIEW_CONFIRM ] + navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, + "domain_name_unknown_chain", + moves) + + +def test_send_fund_domain_too_long(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator): + app_client = EthAppClient(backend) challenge = common(app_client) try: - app_client.provide_domain_name(challenge, "ledger" + "0"*25 + ".eth", ADDR) + with app_client.provide_domain_name(challenge, "ledger" + "0"*25 + ".eth", ADDR): + pass except ExceptionRAPDU as e: assert e.status == StatusWord.INVALID_DATA else: assert False # An exception should have been raised -def test_send_fund_domain_invalid_character(app_client: EthereumClient): + +def test_send_fund_domain_invalid_character(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator): + app_client = EthAppClient(backend) challenge = common(app_client) try: - app_client.provide_domain_name(challenge, "l\xe8dger.eth", ADDR) + with app_client.provide_domain_name(challenge, "l\xe8dger.eth", ADDR): + pass except ExceptionRAPDU as e: assert e.status == StatusWord.INVALID_DATA else: assert False # An exception should have been raised -def test_send_fund_uppercase(app_client: EthereumClient): + +def test_send_fund_uppercase(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator): + app_client = EthAppClient(backend) challenge = common(app_client) try: - app_client.provide_domain_name(challenge, NAME.upper(), ADDR) + with app_client.provide_domain_name(challenge, NAME.upper(), ADDR): + pass except ExceptionRAPDU as e: assert e.status == StatusWord.INVALID_DATA else: assert False # An exception should have been raised -def test_send_fund_domain_non_ens(app_client: EthereumClient): + +def test_send_fund_domain_non_ens(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator): + app_client = EthAppClient(backend) challenge = common(app_client) try: - app_client.provide_domain_name(challenge, "ledger.hte", ADDR) + with app_client.provide_domain_name(challenge, "ledger.hte", ADDR): + pass except ExceptionRAPDU as e: assert e.status == StatusWord.INVALID_DATA else: diff --git a/tests/ragger/test_eip712.py b/tests/ragger/test_eip712.py index 29cb84394..6ff0bc7b3 100644 --- a/tests/ragger/test_eip712.py +++ b/tests/ragger/test_eip712.py @@ -2,10 +2,17 @@ import os import fnmatch from typing import List -from app.client import EthereumClient, SettingType +from ragger.firmware import Firmware +from ragger.backend import BackendInterface +from ragger.navigator import Navigator, NavInsID +from app.client import EthAppClient +from app.settings import SettingID, settings_toggle from eip712 import InputData from pathlib import Path from configparser import ConfigParser +import app.response_parser as ResponseParser +from functools import partial +import time BIP32_PATH = "m/44'/60'/0'/0/0" @@ -30,19 +37,52 @@ def filtering(request) -> bool: return request.param -def test_eip712_legacy(app_client: EthereumClient): - v, r, s = app_client.eip712_sign_legacy( - BIP32_PATH, - bytes.fromhex('6137beb405d9ff777172aa879e33edb34a1460e701802746c5ef96e741710e59'), - bytes.fromhex('eb4221181ff3f1a83ea7313993ca9218496e424604ba9492bb4052c03d5c3df8') - ) +def test_eip712_legacy(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator): + app_client = EthAppClient(backend) + with app_client.eip712_sign_legacy( + BIP32_PATH, + bytes.fromhex('6137beb405d9ff777172aa879e33edb34a1460e701802746c5ef96e741710e59'), + bytes.fromhex('eb4221181ff3f1a83ea7313993ca9218496e424604ba9492bb4052c03d5c3df8')): + moves = list() + if firmware.device.startswith("nano"): + moves += [ NavInsID.RIGHT_CLICK ] + if firmware.device == "nanos": + screens_per_hash = 4 + else: + screens_per_hash = 2 + moves += [ NavInsID.RIGHT_CLICK ] * screens_per_hash * 2 + moves += [ NavInsID.BOTH_CLICK ] + else: + moves += [ NavInsID.USE_CASE_REVIEW_TAP ] * 2 + moves += [ NavInsID.USE_CASE_REVIEW_CONFIRM ] + navigator.navigate(moves) + + v, r, s = ResponseParser.signature(app_client.response().data) assert v == bytes.fromhex("1c") assert r == bytes.fromhex("ea66f747173762715751c889fea8722acac3fc35db2c226d37a2e58815398f64") assert s == bytes.fromhex("52d8ba9153de9255da220ffd36762c0b027701a3b5110f0a765f94b16a9dfb55") -def test_eip712_new(app_client: EthereumClient, input_file: Path, verbose: bool, filtering: bool): - if app_client._client.firmware.device == "nanos": + +def autonext(fw: Firmware, nav: Navigator): + moves = list() + if fw.device.startswith("nano"): + moves = [ NavInsID.RIGHT_CLICK ] + else: + moves = [ NavInsID.USE_CASE_REVIEW_TAP ] + nav.navigate(moves, screen_change_before_first_instruction=False, screen_change_after_last_instruction=False) + + +def test_eip712_new(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + input_file: Path, + verbose: bool, + filtering: bool): + app_client = EthAppClient(backend) + if firmware.device == "nanos": pytest.skip("Not supported on LNS") else: test_path = "%s/%s" % (input_file.parent, "-".join(input_file.stem.split("-")[:-1])) @@ -63,12 +103,25 @@ def test_eip712_new(app_client: EthereumClient, input_file: Path, verbose: bool, if not filtering or Path(filter_file).is_file(): if verbose: - app_client.settings_set({ - SettingType.VERBOSE_EIP712: True - }) - - assert InputData.process_file(app_client, input_file, filter_file) == True - v, r, s = app_client.eip712_sign_new(BIP32_PATH) + settings_toggle(firmware, navigator, [SettingID.VERBOSE_EIP712]) + + assert InputData.process_file(app_client, + input_file, + filter_file, + partial(autonext, firmware, navigator)) == True + with app_client.eip712_sign_new(BIP32_PATH, verbose): + time.sleep(0.5) # tight on timing, needed by the CI otherwise might fail sometimes + moves = list() + if firmware.device.startswith("nano"): + if not verbose and not filtering: # need to skip the message hash + moves = [ NavInsID.RIGHT_CLICK ] * 2 + moves += [ NavInsID.BOTH_CLICK ] + else: + if not verbose and not filtering: # need to skip the message hash + moves += [ NavInsID.USE_CASE_REVIEW_TAP ] + moves += [ NavInsID.USE_CASE_REVIEW_CONFIRM ] + navigator.navigate(moves) + v, r, s = ResponseParser.signature(app_client.response().data) #print("[signature]") #print("v = %s" % (v.hex())) #print("r = %s" % (r.hex())) diff --git a/tests/speculos/README.md b/tests/speculos/README.md index c3bb346cb..68d146878 100644 --- a/tests/speculos/README.md +++ b/tests/speculos/README.md @@ -11,9 +11,8 @@ These tests are implemented in Python with the `SpeculosClient` interface which Python dependencies are listed in [requirements.txt](requirements.txt) ```shell -python3 -m pip install --extra-index-url https://test.pypi.org/simple/ -r requirements.txt +python3 -m pip install -r requirements.txt ``` -> The extra index allows to fetch the latest version of Speculos. ## Usage @@ -47,4 +46,4 @@ pytest --model nanox --path ./elfs/nanox.elf # Execute specific test: pytest --model nanox --path ./elfs/nanox.elf test_pubkey_cmd.py -``` \ No newline at end of file +``` diff --git a/tests/speculos/test_configuration_cmd.py b/tests/speculos/test_configuration_cmd.py index 1d848391b..8027b2cf8 100644 --- a/tests/speculos/test_configuration_cmd.py +++ b/tests/speculos/test_configuration_cmd.py @@ -1,10 +1,10 @@ def test_configuration(cmd): if cmd.model == "nanos": - assert cmd.get_configuration() == (14, 1, 10, 2) + assert cmd.get_configuration() == (14, 1, 10, 3) if cmd.model == "nanox": - assert cmd.get_configuration() == (14, 1, 10, 2) + assert cmd.get_configuration() == (14, 1, 10, 3) if cmd.model == "nanosp": - assert cmd.get_configuration() == (14, 1, 10, 2) + assert cmd.get_configuration() == (14, 1, 10, 3) diff --git a/tools/build_sdk.py b/tools/build_sdk.py index a808e4aed..552bb25cf 100755 --- a/tools/build_sdk.py +++ b/tools/build_sdk.py @@ -82,10 +82,13 @@ def extract_from_c_files(sources, nodes_to_extract): def merge_headers(sources, nodes_to_extract): includes = [ + '#include ', + '#include ', '#include "os.h"', '#include "cx.h"', - '#include ', - '#include ' + '#ifdef HAVE_NBGL', + '#include "nbgl_types.h"', + '#endif' ] body = extract_from_headers(sources, nodes_to_extract) @@ -156,11 +159,12 @@ def merge_c_files(sources, nodes_to_extract): "src/shared_context.h", "src/eth_plugin_internal.h", "src/nft.h", + "src/swap_lib_calls.h" ] nodes_to_extract = { "#define": ["MAX_TICKER_LEN", "ADDRESS_LENGTH", "INT256_LENGTH", "WEI_TO_ETHER", "SELECTOR_SIZE", "PARAMETER_LENGTH", "RUN_APPLICATION", "COLLECTION_NAME_MAX_LEN"], "typedef enum": [], - "typedef struct": ["tokenDefinition_t", "txInt256_t", "txContent_t", "nftInfo_t"], + "typedef struct": ["tokenDefinition_t", "txInt256_t", "txContent_t", "nftInfo_t", "caller_app_t"], "typedef union": ["extraInfo_t"], "__attribute__((no_instrument_function)) inline": ["int allzeroes"], "const": ["HEXDIGITS"],