diff --git a/Makefile b/Makefile index c03f1fee..84d19b50 100644 --- a/Makefile +++ b/Makefile @@ -15,11 +15,7 @@ # limitations under the License. #******************************************************************************* -APPNAME = "Cardano ADA" -APPVERSION_M = 6 -APPVERSION_N = 1 -APPVERSION_P = 2 -APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)" +# based on https://github.com/LedgerHQ/app-boilerplate/blob/master/Makefile ifeq ($(BOLOS_SDK),) $(error Environment variable BOLOS_SDK is not set) @@ -27,174 +23,175 @@ endif include $(BOLOS_SDK)/Makefile.defines -ifeq ($(TARGET_NAME),TARGET_NANOS) - ICONNAME=icon_ada_nanos.gif -else ifeq ($(TARGET_NAME),TARGET_STAX) - ICONNAME=icon_ada_stax.gif -else - ICONNAME=icon_ada_nanox.gif -endif - -############## -# Compiler # -############## - -# based in part on https://interrupt.memfault.com/blog/best-and-worst-gcc-clang-compiler-flags -WERROR := -Werror=return-type -Werror=parentheses -Werror=format-security - -CC := $(CLANGPATH)clang -CFLAGS += -std=gnu99 -Wall -Wextra -Wuninitialized -Wshadow -Wformat=2 -Wwrite-strings -Wundef -fno-common $(WERROR) - -AS := $(GCCPATH)arm-none-eabi-gcc -LD := $(GCCPATH)arm-none-eabi-gcc -LDFLAGS += -Wall -LDLIBS += -lm -lgcc -lc - - -############ -# Platform # -############ - -DEFINES += OS_IO_SEPROXYHAL -ifneq ($(TARGET_NAME),TARGET_STAX) -DEFINES += HAVE_BAGL -endif -DEFINES += HAVE_SPRINTF HAVE_SNPRINTF_FORMAT_U -DEFINES += APPVERSION=\"$(APPVERSION)\" -DEFINES += MAJOR_VERSION=$(APPVERSION_M) MINOR_VERSION=$(APPVERSION_N) PATCH_VERSION=$(APPVERSION_P) - -## USB HID? -DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=4 IO_HID_EP_LENGTH=64 HAVE_USB_APDU +######################################## +# Mandatory configuration # +######################################## +# Application name +APPNAME = "Cardano ADA" -## USB U2F -DEFINES += HAVE_U2F HAVE_IO_U2F U2F_PROXY_MAGIC=\"ADA\" USB_SEGMENT_SIZE=64 - -## WEBUSB -#WEBUSB_URL = https://www.ledger.com/pages/supported-crypto-assets -#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="" - -## BLUETOOTH -ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX)) - DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000 HAVE_BLE_APDU -endif - -## Protect stack overflows -DEFINES += HAVE_BOLOS_APP_STACK_CANARY +# Application version +APPVERSION_M = 6 +APPVERSION_N = 1 +APPVERSION_P = 2 +APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)" + +# Application source files +APP_SOURCE_PATH += src + +# Application icons following guidelines: +# https://developers.ledger.com/docs/embedded-app/design-requirements/#device-icon +ICON_NANOS = icons/app_ada_16px.gif +ICON_NANOX = icons/app_ada_14px.gif +ICON_NANOSP = icons/app_ada_14px.gif +ICON_STAX = icons/app_ada_32px.gif + +# Application allowed derivation curves. +# Possibles curves are: secp256k1, secp256r1, ed25519 and bls12381g1 +# If your app needs it, you can specify multiple curves by using: +# `CURVE_APP_LOAD_PARAMS = ` +CURVE_APP_LOAD_PARAMS = ed25519 + +# Application allowed derivation paths. +# You should request a specific path for your app. +# This serve as an isolation mechanism. +# Most application will have to request a path according to the BIP-0044 +# and SLIP-0044 standards. +# If your app needs it, you can specify multiple path by using: +# `PATH_APP_LOAD_PARAMS = "44'/1'" "45'/1'"` +PATH_APP_LOAD_PARAMS = "44'/1815'" "1852'/1815'" "1853'/1815'" "1854'/1815'" "1855'/1815'" "1694'/1815'" + +# Setting to allow building variant applications +# - is the name of the parameter which should be set +# to specify the variant that should be build. +# - a list of variant that can be build using this app code. +# * It must at least contains one value. +# * Values can be the app ticker or anything else but should be unique. +VARIANT_PARAM = COIN +VARIANT_VALUES = cardano_ada + +# Use developer build for testing (e.g. on Speculos) +#DEVEL = 1 -ifeq ($(TARGET_NAME),TARGET_NANOS) -DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 +ifeq ($(DEVEL), 1) + DEFINES += DEVEL + # Automatically confirm all prompts to avoid manually clicking through UI + DEFINES += HEADLESS + # Enabling DEBUG flag will enable PRINTF and disable optimizations + DEBUG = 1 else -DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300 -DEFINES += HAVE_GLO096 -ifneq ($(TARGET_NAME),TARGET_STAX) -DEFINES += HAVE_BAGL BAGL_WIDTH=128 BAGL_HEIGHT=64 -DEFINES += HAVE_UX_FLOW + DEFINES += RESET_ON_CRASH endif -ifeq ($(TARGET_NAME),TARGET_STAX) -DEFINES += NBGL_QRCODE -SDK_SOURCE_PATH += qrcode -endif -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 - -DEFINES += RESET_ON_CRASH - -## Use developer build -#DEVEL = 1 -#DEFINES += HEADLESS - -# Enabling debug PRINTF -ifeq ($(DEVEL), 1) - DEFINES += DEVEL HAVE_PRINTF - ifeq ($(TARGET_NAME),TARGET_NANOS) - DEFINES += PRINTF=screen_printf +# restricted features for Nano S +# but not in DEVEL mode where we usually want to test all features with HEADLESS +ifeq ($(TARGET_NAME), TARGET_NANOS) + ifneq ($(DEVEL), 1) + APP_XS = 1 else - DEFINES += PRINTF=mcu_usb_printf + APP_XS = 0 endif else - DEFINES += PRINTF\(...\)= + APP_XS = 0 endif - -################## -# Dependencies # -################## - -# import rules to compile glyphs -include $(BOLOS_SDK)/Makefile.glyphs - -### computed variables -APP_SOURCE_PATH += src -SDK_SOURCE_PATH += lib_stusb lib_stusb_impl lib_u2f - -ifneq ($(TARGET_NAME),TARGET_STAX) -SDK_SOURCE_PATH += lib_ux +ifeq ($(APP_XS), 1) + DEFINES += APP_XS +else + # features not included in the Nano S app + DEFINES += APP_FEATURE_OPCERT + DEFINES += APP_FEATURE_NATIVE_SCRIPT_HASH + DEFINES += APP_FEATURE_POOL_REGISTRATION + DEFINES += APP_FEATURE_POOL_RETIREMENT + DEFINES += APP_FEATURE_BYRON_ADDRESS_DERIVATION + DEFINES += APP_FEATURE_BYRON_PROTOCOL_MAGIC_CHECK endif - -ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX)) - SDK_SOURCE_PATH += lib_blewbxx lib_blewbxx_impl +# always include this, it's important for Plutus users +DEFINES += APP_FEATURE_TOKEN_MINTING + +######################################## +# Application custom permissions # +######################################## +# See SDK `include/appflags.h` for the purpose of each permission +#HAVE_APPLICATION_FLAG_DERIVE_MASTER = 1 +#HAVE_APPLICATION_FLAG_GLOBAL_PIN = 1 +HAVE_APPLICATION_FLAG_BOLOS_SETTINGS = 1 +#HAVE_APPLICATION_FLAG_LIBRARY = 1 + +######################################## +# Application communication interfaces # +######################################## +ENABLE_BLUETOOTH = 1 +#ENABLE_NFC = 1 + +######################################## +# NBGL custom features # +######################################## +ENABLE_NBGL_QRCODE = 1 +#ENABLE_NBGL_KEYBOARD = 1 +#ENABLE_NBGL_KEYPAD = 1 + +######################################## +# Features disablers # +######################################## +# These advanced settings allow to disable some feature that are by +# default enabled in the SDK `Makefile.standard_app`. +#DISABLE_STANDARD_APP_FILES = 1 +#DISABLE_DEFAULT_IO_SEPROXY_BUFFER_SIZE = 1 # To allow custom size declaration +#DISABLE_STANDARD_APP_DEFINES = 1 # Will set all the following disablers +#DISABLE_STANDARD_SNPRINTF = 1 +#DISABLE_STANDARD_USB = 1 +#DISABLE_STANDARD_WEBUSB = 1 + +ifeq ($(TARGET_NAME), TARGET_NANOS) + DISABLE_STANDARD_BAGL_UX_FLOW = 1 endif -################ -# Default rule # -################ +######################################## +# Additional configuration # +######################################## -all: default - - -############## -# Build # -############## - -listvariants: - @echo VARIANTS COIN cardano_ada - -# part of CI -analyze: clean - scan-build --use-cc=clang -analyze-headers -enable-checker security -enable-checker unix -enable-checker valist -o scan-build --status-bugs make default +# USB U2F +DEFINES += HAVE_U2F HAVE_IO_U2F U2F_PROXY_MAGIC=\"ADA\" +SDK_SOURCE_PATH += lib_u2f -############## -# Load # -############## +# Protect against stack overflows +DEFINES += HAVE_BOLOS_APP_STACK_CANARY -NANOS_ID = 1 +# mnemonic and PIN for testing on a physical device / Speculos WORDS = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" PIN = 5555 -APP_LOAD_PARAMS =--appFlags 0x200 --curve ed25519 --path "44'/1815'" --path "1852'/1815'" --path "1853'/1815'" --path "1854'/1815'" --path "1855'/1815'" --path "1694'/1815'" -APP_LOAD_PARAMS += $(COMMON_LOAD_PARAMS) - -load: - python -m ledgerblue.loadApp $(APP_LOAD_PARAMS) +# based in part on https://interrupt.memfault.com/blog/best-and-worst-gcc-clang-compiler-flags +CFLAGS += -Wuninitialized -Wreturn-type -Wparentheses -fno-common -delete: - python -m ledgerblue.deleteApp $(COMMON_DELETE_PARAMS) +######################################## +# Additional targets # +######################################## -seed: - python -m ledgerblue.hostOnboard --id $(NANOS_ID) --words $(WORDS) --pin $(PIN) +# code style +format: + astyle --options=.astylerc "src/*.h" "src/*.c" +# prints app size, max is about 140K +size: all + $(GCCPATH)arm-none-eabi-size --format=gnu bin/app.elf -############## -# Style # -############## +# device-specific builds +nanos: clean + BOLOS_SDK=$(NANOS_SDK) make -format: - astyle --options=.astylerc "src/*.h" "src/*.c" --exclude=src/glyphs.h --exclude=src/glyphs.c --ignore-exclude-errors +nanosp: clean + BOLOS_SDK=$(NANOSP_SDK) make +nanox: clean + BOLOS_SDK=$(NANOX_SDK) make -############## -# Size # -############## +stax: clean + BOLOS_SDK=$(STAX_SDK) make -# prints app size, max is about 140K +# part of CI +analyze: clean + scan-build --use-cc=clang -analyze-headers -enable-checker security -enable-checker unix -enable-checker valist -o scan-build --status-bugs make default -size: all - $(GCCPATH)arm-none-eabi-size --format=gnu bin/app.elf -# import generic rules from the sdk -include $(BOLOS_SDK)/Makefile.rules +include $(BOLOS_SDK)/Makefile.standard_app diff --git a/doc/build.md b/doc/build.md index 14a11485..b94de09c 100644 --- a/doc/build.md +++ b/doc/build.md @@ -5,7 +5,7 @@ - Install Docker - Pull the required containers as discussed in https://github.com/LedgerHQ/ledger-app-builder/ (lite container is sufficient for a C build): - `sudo docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest` + `docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest` ## Compiling the app diff --git a/doc/features.md b/doc/features.md new file mode 100644 index 00000000..ec9745f3 --- /dev/null +++ b/doc/features.md @@ -0,0 +1,11 @@ +# Features (not) available on specific Ledger devices + +Nano S has a very limited space for storing applications. It is not enough to fit all Cardano features there, so some of them are only available on Nano S+ and other more spacious Ledger devices (e.g. Nano X and Stax). + +The features not supported on Nano S, Cardano app version 7 and above: +* pool registration and retirement +* signing of operational certificates +* computation of native script hashes +* details in Byron change outputs (only the address is shown) + +Details can be found in [Makefile](../Makefile) and in the code (search for compilation flags beginning with `APP_FEATURE_`). diff --git a/doc/ins_get_public_keys.md b/doc/ins_get_public_keys.md index e3035d82..fc304d72 100644 --- a/doc/ins_get_public_keys.md +++ b/doc/ins_get_public_keys.md @@ -80,8 +80,6 @@ Concatenation of `pub_key` and `chain_code` representing the extended public key - Ledger might impose more restrictions, see implementation of `policyForGetExtendedPublicKey` in [src/securityPolicy.c](../src/securityPolicy.c) for details - calculate extended public key - respond with extended public key - + **TODOs** - ❓(IOHK): Should we also support BTC app like token validation? (Note: Token validation is to prevent concurrent access to the Ledger by two different host apps which could confuse user into performing wrong actions) -- ❓(IOHK): Should we support permanent app setting where Ledger forces user to acknowledge public key retrieval before sending it to host? (Note: probably not in the first version of the app) -- ❓(IOHK): Should there be an option to show the public key on display? Is it useful in any way? (Note: probably not) diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index fe7e9fe6..0d324582 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -142,6 +142,15 @@ add_compile_definitions( HAVE_HASH HAVE_SHA256 HAVE_SHA3 + + # include all app features, incl. those removed from Nano S + APP_FEATURE_OPCERT + APP_FEATURE_NATIVE_SCRIPT_HASH + APP_FEATURE_POOL_REGISTRATION + APP_FEATURE_POOL_RETIREMENT + APP_FEATURE_BYRON_ADDRESS_DERIVATION + APP_FEATURE_BYRON_PROTOCOL_MAGIC_CHECK + APP_FEATURE_TOKEN_MINTING ) set(SOURCE diff --git a/icon_ada_nanox.gif b/icons/app_ada_14px.gif similarity index 100% rename from icon_ada_nanox.gif rename to icons/app_ada_14px.gif diff --git a/icon_ada_nanos.gif b/icons/app_ada_16px.gif similarity index 100% rename from icon_ada_nanos.gif rename to icons/app_ada_16px.gif diff --git a/icon_ada_stax.gif b/icons/app_ada_32px.gif similarity index 100% rename from icon_ada_stax.gif rename to icons/app_ada_32px.gif diff --git a/src/addressUtilsByron.c b/src/addressUtilsByron.c index 078706e8..bb3c01a1 100644 --- a/src/addressUtilsByron.c +++ b/src/addressUtilsByron.c @@ -7,6 +7,15 @@ #include "crc32.h" #include "bufView.h" +#if defined(APP_FEATURE_BYRON_ADDRESS_DERIVATION) || defined(APP_FEATURE_BYRON_PROTOCOL_MAGIC_CHECK) + +static const size_t ADDRESS_ROOT_SIZE = 28; +static const size_t PROTOCOL_MAGIC_ADDRESS_ATTRIBUTE_KEY = 2; + +#endif + +#ifdef APP_FEATURE_BYRON_ADDRESS_DERIVATION + enum { CARDANO_ADDRESS_TYPE_PUBKEY = 0, /* @@ -15,9 +24,6 @@ enum { */ }; -static const size_t ADDRESS_ROOT_SIZE = 28; -static const size_t PROTOCOL_MAGIC_ADDRESS_ATTRIBUTE_KEY = 2; - void addressRootFromExtPubKey( const extendedPublicKey_t* extPubKey, uint8_t* outBuffer, size_t outSize @@ -31,7 +37,7 @@ void addressRootFromExtPubKey( { // [0, [0, publicKey:chainCode], Map(0)] - // TODO(ppershing): what are the first two 0 constants? + // Note(ppershing): what are the first two 0 constants? view_appendToken(&cbor, CBOR_TYPE_ARRAY, 3); { view_appendToken(&cbor, CBOR_TYPE_UNSIGNED, CARDANO_ADDRESS_TYPE_PUBKEY); @@ -136,6 +142,56 @@ size_t cborPackRawAddressWithChecksum( return view_processedSize(&output); } +size_t deriveRawAddress( + const bip44_path_t* pathSpec, uint32_t protocolMagic, + uint8_t* outBuffer, size_t outSize +) +{ + ASSERT(outSize < BUFFER_SIZE_PARANOIA); + + uint8_t addressRoot[28] = {0}; + { + extendedPublicKey_t extPubKey; + + deriveExtendedPublicKey(pathSpec, &extPubKey); + + addressRootFromExtPubKey( + &extPubKey, + addressRoot, SIZEOF(addressRoot) + ); + } + + return cborEncodePubkeyAddressInner( + addressRoot, SIZEOF(addressRoot), + protocolMagic, + outBuffer, outSize + ); +} + +size_t deriveAddress_byron( + const bip44_path_t* pathSpec, uint32_t protocolMagic, + uint8_t* outBuffer, size_t outSize +) +{ + ASSERT(outSize < BUFFER_SIZE_PARANOIA); + + uint8_t rawAddressBuffer[40] = {0}; + size_t rawAddressSize = deriveRawAddress( + pathSpec, protocolMagic, + rawAddressBuffer, SIZEOF(rawAddressBuffer) + ); + + return cborPackRawAddressWithChecksum( + rawAddressBuffer, rawAddressSize, + outBuffer, outSize + ); + +} + +#endif // APP_FEATURE_BYRON_ADDRESS_DERIVATION + +#ifdef APP_FEATURE_BYRON_PROTOCOL_MAGIC_CHECK + static uint64_t parseToken(read_view_t* view, uint8_t type) { const cbor_token_t token = view_parseToken(view); @@ -166,7 +222,6 @@ static size_t parseBytesSizeToken(read_view_t* view) return parsedSizeDowncasted; } - uint32_t extractProtocolMagic( const uint8_t* addressBuffer, size_t addressSize ) @@ -252,48 +307,4 @@ uint32_t extractProtocolMagic( return protocolMagic; } -size_t deriveRawAddress( - const bip44_path_t* pathSpec, uint32_t protocolMagic, - uint8_t* outBuffer, size_t outSize -) -{ - ASSERT(outSize < BUFFER_SIZE_PARANOIA); - - uint8_t addressRoot[28] = {0}; - { - extendedPublicKey_t extPubKey; - - deriveExtendedPublicKey(pathSpec, &extPubKey); - - addressRootFromExtPubKey( - &extPubKey, - addressRoot, SIZEOF(addressRoot) - ); - } - - return cborEncodePubkeyAddressInner( - addressRoot, SIZEOF(addressRoot), - protocolMagic, - outBuffer, outSize - ); -} - -size_t deriveAddress_byron( - const bip44_path_t* pathSpec, uint32_t protocolMagic, - uint8_t* outBuffer, size_t outSize -) -{ - ASSERT(outSize < BUFFER_SIZE_PARANOIA); - - uint8_t rawAddressBuffer[40] = {0}; - size_t rawAddressSize = deriveRawAddress( - pathSpec, protocolMagic, - rawAddressBuffer, SIZEOF(rawAddressBuffer) - ); - - return cborPackRawAddressWithChecksum( - rawAddressBuffer, rawAddressSize, - outBuffer, outSize - ); - -} +#endif // APP_FEATURE_BYRON_PROTOCOL_MAGIC_CHECK diff --git a/src/addressUtilsByron.h b/src/addressUtilsByron.h index e5d275a0..d107993c 100644 --- a/src/addressUtilsByron.h +++ b/src/addressUtilsByron.h @@ -4,19 +4,27 @@ #include "common.h" #include "bip44.h" +#ifdef APP_FEATURE_BYRON_ADDRESS_DERIVATION + size_t deriveAddress_byron( const bip44_path_t* pathSpec, uint32_t protocolMagic, uint8_t* outBuffer, size_t outSize ); +#endif // APP_FEATURE_BYRON_ADDRESS_DERIVATION + +#ifdef APP_FEATURE_BYRON_PROTOCOL_MAGIC_CHECK + // Note: validates the overall address structure at the same time uint32_t extractProtocolMagic( const uint8_t* addressBuffer, size_t addressSize ); +#endif // APP_FEATURE_BYRON_PROTOCOL_MAGIC_CHECK + -#ifdef DEVEL +#if defined(DEVEL) && !defined(APP_XS) void run_addressUtilsByron_test(); #endif // DEVEL diff --git a/src/addressUtilsByron_test.c b/src/addressUtilsByron_test.c index 945418e5..444e3bb6 100644 --- a/src/addressUtilsByron_test.c +++ b/src/addressUtilsByron_test.c @@ -1,4 +1,4 @@ -#ifdef DEVEL +#if defined(DEVEL) && !defined(APP_XS) #include "addressUtilsByron.h" #include "cardano.h" diff --git a/src/addressUtilsShelley.c b/src/addressUtilsShelley.c index 7740708e..f6db8d23 100644 --- a/src/addressUtilsShelley.c +++ b/src/addressUtilsShelley.c @@ -439,8 +439,6 @@ size_t deriveAddress(const addressParams_t* addressParams, uint8_t* outBuffer, s ASSERT(outSize < BUFFER_SIZE_PARANOIA); ASSERT(isValidAddressParams(addressParams)); - const bip44_path_t* spendingPath = &addressParams->spendingKeyPath; - // shelley switch (addressParams->type) { case BASE_PAYMENT_KEY_STAKE_KEY: @@ -458,8 +456,16 @@ size_t deriveAddress(const addressParams_t* addressParams, uint8_t* outBuffer, s case REWARD_KEY: case REWARD_SCRIPT: return deriveAddress_reward(addressParams, outBuffer, outSize); + + #ifdef APP_FEATURE_BYRON_ADDRESS_DERIVATION case BYRON: - return deriveAddress_byron(spendingPath, addressParams->protocolMagic, outBuffer, outSize); + return deriveAddress_byron( + &addressParams->spendingKeyPath, + addressParams->protocolMagic, + outBuffer, outSize + ); + #endif // APP_FEATURE_BYRON_ADDRESS_DERIVATION + default: ASSERT(false); } @@ -698,6 +704,12 @@ bool isValidAddressParams(const addressParams_t* params) #define CHECK(cond) if (!(cond)) return false if (params->type != BYRON) { CHECK(isValidNetworkId(params->networkId)); + } else { + // code for Byron address derivation not available in XS app + // thus we cannot process address params + #ifndef APP_FEATURE_BYRON_ADDRESS_DERIVATION + return false; + #endif } CHECK(isValidStakingInfo(params)); diff --git a/src/main.c b/src/app_main.c similarity index 77% rename from src/main.c rename to src/app_main.c index 560e21cb..54f77b0f 100644 --- a/src/main.c +++ b/src/app_main.c @@ -22,16 +22,12 @@ #include #include -#include -#include -#include "getVersion.h" #include "handlers.h" #include "state.h" #include "errors.h" -#include "menu.h" #include "assert.h" -#include "io.h" +#include "cardano_io.h" #ifdef HAVE_BAGL #include "uiScreens_bagl.h" @@ -50,8 +46,16 @@ static const uint8_t CLA = 0xD7; // subsequent io_exchange call. The handler may also throw an exception, which // will be caught, converted to an error code, appended to the response APDU, // and sent in the next io_exchange call. -static void cardano_main(void) +void app_main() { + ui_idle(); + + #ifdef HAVE_NBGL + ui_idle_flow(); + #endif // HAVE_NBGL + + io_state = IO_EXPECT_IO; + volatile size_t rx = 0; volatile size_t tx = 0; volatile uint8_t flags = 0; @@ -65,7 +69,7 @@ static void cardano_main(void) // In sia_main, this TRY block serves to catch any thrown exceptions // and convert them to response codes, which are then sent in APDUs. // However, EXCEPTION_IO_RESET will be re-thrown and caught by the - // "true" main function defined at the bottom of this file. + // "true" main function defined in the SDK. BEGIN_TRY { TRY { rx = tx; @@ -124,7 +128,6 @@ static void cardano_main(void) VALIDATE(header->ins == currentInstruction, ERR_STILL_IN_CALL); } - // Note: handlerFn is responsible for calling io_send // either during its call or subsequent UI actions handlerFn(header->p1, @@ -173,75 +176,3 @@ static void cardano_main(void) END_TRY; } } - - -// Everything below this point is Ledger magic. And the magic isn't well- -// documented, so if you want to understand it, you'll need to read the -// source, which you can find in the nanos-secure-sdk repo. Fortunately, you -// don't need to understand any of this in order to write an app. -// - - -static void app_exit(void) -{ - BEGIN_TRY_L(exit) { - TRY_L(exit) { - os_sched_exit(-1); - } - FINALLY_L(exit) { - } - } - END_TRY_L(exit); -} - -__attribute__((section(".boot"))) int main(void) -{ - // exit critical section - __asm volatile("cpsie i"); - - for (;;) { - UX_INIT(); - os_boot(); - BEGIN_TRY { - TRY { - io_seproxyhal_init(); - - #if defined(HAVE_BLE) - // grab the current plane mode setting - G_io_app.plane_mode = os_setting_get(OS_SETTING_PLANEMODE, NULL, 0); - #endif - - USB_power(0); - USB_power(1); - ui_idle(); - - #ifdef HAVE_NBGL - ui_idle_flow(); - #endif // HAVE_NBGL - - #if defined(HAVE_BLE) - BLE_power(0, NULL); - BLE_power(1, NULL); - #endif - - io_state = IO_EXPECT_IO; - cardano_main(); - } - CATCH(EXCEPTION_IO_RESET) - { - // reset IO and UX before continuing - CLOSE_TRY; - continue; - } - CATCH_ALL { - CLOSE_TRY; - break; - } - FINALLY { - } - } - END_TRY; - } - app_exit(); - return 0; -} diff --git a/src/cardano.h b/src/cardano.h index f0cfe29b..03f13e01 100644 --- a/src/cardano.h +++ b/src/cardano.h @@ -160,6 +160,8 @@ typedef struct { // ============================== NATIVE SCRIPTS ============================== +#ifdef APP_FEATURE_NATIVE_SCRIPT_HASH + // depth of n means it can handle up to n-1 levels of nesting #define MAX_SCRIPT_DEPTH 11 @@ -172,4 +174,6 @@ typedef enum { NATIVE_SCRIPT_INVALID_HEREAFTER = 5, } native_script_type; +#endif // APP_FEATURE_NATIVE_SCRIPT_HASH + #endif // H_CARDANO_APP_CARDANO diff --git a/src/io.c b/src/cardano_io.c similarity index 97% rename from src/io.c rename to src/cardano_io.c index a85bfc50..0548085e 100644 --- a/src/io.c +++ b/src/cardano_io.c @@ -1,4 +1,4 @@ -#include "io.h" +#include "cardano_io.h" #include "common.h" #include "ui.h" @@ -93,8 +93,6 @@ void io_seproxyhal_display(const bagl_element_t* element) } #endif -unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B] = {0}; - #ifndef FUZZING unsigned char io_event(unsigned char channel MARK_UNUSED) { @@ -127,7 +125,7 @@ unsigned char io_event(unsigned char channel MARK_UNUSED) case SEPROXYHAL_TAG_FINGER_EVENT: UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer); break; - #endif // HAVE_NBGL + #endif // HAVE_NBGL case SEPROXYHAL_TAG_TICKER_EVENT: UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, { diff --git a/src/io.h b/src/cardano_io.h similarity index 96% rename from src/io.h rename to src/cardano_io.h index 13d23f19..280bbf07 100644 --- a/src/io.h +++ b/src/cardano_io.h @@ -4,9 +4,10 @@ #include #include #include -#include #include "ui.h" +extern uint8_t G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; + enum { P1_UNUSED = 0, P2_UNUSED = 0 diff --git a/src/common.h b/src/common.h index 5f7f50a7..82befc1a 100644 --- a/src/common.h +++ b/src/common.h @@ -12,5 +12,5 @@ // ours #include "assert.h" #include "errors.h" -#include "io.h" +#include "cardano_io.h" #include "utils.h" diff --git a/src/deriveNativeScriptHash.c b/src/deriveNativeScriptHash.c index cac061f9..de8df37c 100644 --- a/src/deriveNativeScriptHash.c +++ b/src/deriveNativeScriptHash.c @@ -1,3 +1,5 @@ +#ifdef APP_FEATURE_NATIVE_SCRIPT_HASH + #include "deriveNativeScriptHash.h" #include "deriveNativeScriptHash_ui.h" #include "state.h" @@ -304,3 +306,5 @@ void deriveNativeScriptHash_handleAPDU( } #undef TRACE_WITH_CTX + +#endif // APP_FEATURE_NATIVE_SCRIPT_HASH diff --git a/src/deriveNativeScriptHash.h b/src/deriveNativeScriptHash.h index 2044a1d8..b26e59c4 100644 --- a/src/deriveNativeScriptHash.h +++ b/src/deriveNativeScriptHash.h @@ -1,6 +1,8 @@ #ifndef H_CARDANO_APP_DERIVE_NATIVE_SCRIPT_HASH #define H_CARDANO_APP_DERIVE_NATIVE_SCRIPT_HASH +#ifdef APP_FEATURE_NATIVE_SCRIPT_HASH + #include "bip44.h" #include "cardano.h" #include "common.h" @@ -48,4 +50,6 @@ typedef struct { ui_native_script_type ui_scriptType; } ins_derive_native_script_hash_context_t; +#endif // APP_FEATURE_NATIVE_SCRIPT_HASH + #endif // H_CARDANO_APP_DERIVE_NATIVE_SCRIPT_HASH diff --git a/src/deriveNativeScriptHash_ui.c b/src/deriveNativeScriptHash_ui.c index 716d3023..99bb376d 100644 --- a/src/deriveNativeScriptHash_ui.c +++ b/src/deriveNativeScriptHash_ui.c @@ -1,3 +1,5 @@ +#ifdef APP_FEATURE_NATIVE_SCRIPT_HASH + #include "deriveNativeScriptHash.h" #include "deriveNativeScriptHash_ui.h" #include "state.h" @@ -338,3 +340,5 @@ void deriveNativeScriptHash_displayNativeScriptHash_policyId() fill_and_display_if_required("Policy ID", bufferHex, deriveNativeScriptHash_displayNativeScriptHash_finish, respond_with_user_reject); #endif // HAVE_BAGL } + +#endif // APP_FEATURE_NATIVE_SCRIPT_HASH diff --git a/src/deriveNativeScriptHash_ui.h b/src/deriveNativeScriptHash_ui.h index 95460806..b4193c34 100644 --- a/src/deriveNativeScriptHash_ui.h +++ b/src/deriveNativeScriptHash_ui.h @@ -1,5 +1,8 @@ #ifndef H_CARDANO_APP_DERIVE_NATIVE_SCRIPT_HASH_UI #define H_CARDANO_APP_DERIVE_NATIVE_SCRIPT_HASH_UI + +#ifdef APP_FEATURE_NATIVE_SCRIPT_HASH + enum { DISPLAY_UI_STEP_POSITION = 200, #ifdef HAVE_NBGL @@ -17,4 +20,7 @@ void deriveNativeScriptHash_displayNativeScriptHash_callback(); void deriveNativeScriptHash_displayNativeScriptHash_bech32(); void deriveNativeScriptHash_displayNativeScriptHash_policyId(); + +#endif // APP_FEATURE_NATIVE_SCRIPT_HASH + #endif // H_CARDANO_APP_DERIVE_NATIVE_SCRIPT_HASH_UI diff --git a/src/getVersion.c b/src/getVersion.c index 3edf206b..2c831dfc 100644 --- a/src/getVersion.c +++ b/src/getVersion.c @@ -6,8 +6,9 @@ enum { - FLAG_DEVEL = 1, - + FLAG_DEVEL = 1 << 0, +// FLAG_HEADLESS = 1 << 1, + FLAG_APP_XS = 1 << 2, }; void getVersion_handleAPDU( @@ -40,12 +41,15 @@ void getVersion_handleAPDU( .major = MAJOR_VERSION, .minor = MINOR_VERSION, .patch = PATCH_VERSION, - .flags = 0, + .flags = 0, // see below }; #ifdef DEVEL response.flags |= FLAG_DEVEL; #endif // DEVEL + #ifdef APP_XS + response.flags |= FLAG_APP_XS; + #endif // APP_XS io_send_buf(SUCCESS, (uint8_t*) &response, sizeof(response)); ui_idle(); diff --git a/src/handlers.c b/src/handlers.c index 4c6cc5a1..db9792f4 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -29,11 +29,15 @@ handler_fn_t* lookupHandler(uint8_t ins) // 0x1* - public-key/address related CASE(0x10, getPublicKeys_handleAPDU); CASE(0x11, deriveAddress_handleAPDU); + #ifdef APP_FEATURE_NATIVE_SCRIPT_HASH CASE(0x12, deriveNativeScriptHash_handleAPDU); + #endif // APP_FEATURE_NATIVE_SCRIPT_HASH // 0x2* - signing related CASE(0x21, signTx_handleAPDU); + #ifdef APP_FEATURE_OPCERT CASE(0x22, signOpCert_handleAPDU); + #endif // APP_FEATURE_OPCERT CASE(0x23, signCVote_handleAPDU); #ifdef DEVEL diff --git a/src/ipUtils.c b/src/ipUtils.c index 7b6fc89f..2cbcfc31 100644 --- a/src/ipUtils.c +++ b/src/ipUtils.c @@ -1,3 +1,5 @@ +#ifdef APP_FEATURE_POOL_REGISTRATION + /* * Taken from glibc: * https://www.gnu.org/software/libc/sources.html @@ -159,3 +161,5 @@ void inet_ntop6 (const uint8_t* src, char* dst, size_t dstSize) strncpy(dst, tmp, dstSize); } + +#endif // APP_FEATURE_POOL_REGISTRATION diff --git a/src/ipUtils.h b/src/ipUtils.h index 111fa076..333945e8 100644 --- a/src/ipUtils.h +++ b/src/ipUtils.h @@ -1,6 +1,8 @@ #ifndef H_CARDANO_APP_IP_UTILS #define H_CARDANO_APP_IP_UTILS +#ifdef APP_FEATURE_POOL_REGISTRATION + #include "os.h" #define IPV4_STR_SIZE_MAX (sizeof "255.255.255.255") @@ -13,4 +15,6 @@ void inet_ntop6 (const uint8_t* src, char* dst, size_t dstSize); void run_ipUtils_test(); #endif // DEVEL -#endif // H_CARDANO_APP_SIGN_TX_UTILS +#endif // APP_FEATURE_POOL_REGISTRATION + +#endif // H_CARDANO_APP_IP_UTILS diff --git a/src/ipUtils_test.c b/src/ipUtils_test.c index 413bef7c..b54e019f 100644 --- a/src/ipUtils_test.c +++ b/src/ipUtils_test.c @@ -1,4 +1,4 @@ -#ifdef DEVEL +#if defined(DEVEL) && defined(APP_FEATURE_POOL_REGISTRATION) #include "ipUtils.h" #include "utils.h" @@ -55,4 +55,5 @@ void run_ipUtils_test() test3(); } -#endif // DEVEL +#endif // DEVEL && APP_FEATURE_POOL_REGISTRATION + diff --git a/src/messageSigning.c b/src/messageSigning.c index 41e5c00d..4d495ff1 100644 --- a/src/messageSigning.c +++ b/src/messageSigning.c @@ -64,6 +64,7 @@ void getCVoteRegistrationSignature(bip44_path_t* pathSpec, #endif } +#ifdef APP_FEATURE_OPCERT void getOpCertSignature(bip44_path_t* pathSpec, const uint8_t* opCertBodyBuffer, size_t opCertBodySize, uint8_t* outBuffer, size_t outSize) @@ -74,3 +75,4 @@ void getOpCertSignature(bip44_path_t* pathSpec, signRawMessageWithPath(pathSpec, opCertBodyBuffer, opCertBodySize, outBuffer, outSize); } +#endif // APP_FEATURE_OPCERT diff --git a/src/messageSigning.h b/src/messageSigning.h index fbf18f89..e2db31f8 100644 --- a/src/messageSigning.h +++ b/src/messageSigning.h @@ -11,8 +11,10 @@ void getCVoteRegistrationSignature(bip44_path_t* pathSpec, const uint8_t* payloadHashBuffer, size_t payloadHashSize, uint8_t* outBuffer, size_t outSize); +#ifdef APP_FEATURE_OPCERT void getOpCertSignature(bip44_path_t* pathSpec, const uint8_t* opCertBodyBuffer, size_t opCertBodySize, uint8_t* outBuffer, size_t outSize); +#endif // APP_FEATURE_OPCERT #endif // H_CARDANO_APP_MESSAGE_SIGNING diff --git a/src/nativeScriptHashBuilder.c b/src/nativeScriptHashBuilder.c index 6bea3f82..7e4a80b0 100644 --- a/src/nativeScriptHashBuilder.c +++ b/src/nativeScriptHashBuilder.c @@ -1,3 +1,5 @@ +#ifdef APP_FEATURE_NATIVE_SCRIPT_HASH + #include "cbor.h" #include "nativeScriptHashBuilder.h" @@ -227,3 +229,5 @@ void nativeScriptHashBuilder_finalize( #undef APPEND_CBOR #undef _TRACE_BUFFER #undef _TRACE + +#endif // APP_FEATURE_NATIVE_SCRIPT_HASH diff --git a/src/nativeScriptHashBuilder.h b/src/nativeScriptHashBuilder.h index de2653e4..a5508fb1 100644 --- a/src/nativeScriptHashBuilder.h +++ b/src/nativeScriptHashBuilder.h @@ -1,6 +1,8 @@ #ifndef H_CARDANO_APP_NATIVE_SCRIPT_HASH_BUILDER #define H_CARDANO_APP_NATIVE_SCRIPT_HASH_BUILDER +#ifdef APP_FEATURE_NATIVE_SCRIPT_HASH + #include "cardano.h" #include "hash.h" @@ -59,4 +61,6 @@ void nativeScriptHashBuilder_finalize( void run_nativeScriptHashBuilder_test(); /* #endif // DEVEL */ +#endif // APP_FEATURE_NATIVE_SCRIPT_HASH + #endif // H_CARDANO_APP_NATIVE_SCRIPT_HASH_BUILDER diff --git a/src/nativeScriptHashBuilder_test.c b/src/nativeScriptHashBuilder_test.c index c3f2e88c..5bcc340c 100644 --- a/src/nativeScriptHashBuilder_test.c +++ b/src/nativeScriptHashBuilder_test.c @@ -1,4 +1,4 @@ -#ifdef DEVEL +#if defined(DEVEL) && defined(APP_FEATURE_NATIVE_SCRIPT_HASH) #include "hexUtils.h" #include "nativeScriptHashBuilder.h" @@ -105,4 +105,5 @@ void run_nativeScriptHashBuilder_test() #undef FINALIZE #undef BEFORE_EACH #undef BUF_FROM_STR -#endif // DEVEL + +#endif // DEVEL && APP_FEATURE_NATIVE_SCRIPT_HASH diff --git a/src/runTests.c b/src/runTests.c index 8134edaa..29ab61c2 100644 --- a/src/runTests.c +++ b/src/runTests.c @@ -32,6 +32,7 @@ void handleRunTests( // Note: Make sure to have RESET_ON_CRASH flag disabled // as it interferes with tests verifying assertions BEGIN_ASSERT_NOEXCEPT { + PRINTF("Running tests\n"); run_hex_test(); run_base58_test(); @@ -40,17 +41,23 @@ void handleRunTests( run_endian_test(); run_textUtils_test(); run_tokens_test(); + #if defined(APP_FEATURE_POOL_REGISTRATION) run_ipUtils_test(); + #endif run_hash_test(); run_cbor_test(); run_bip44_test(); run_key_derivation_test(); + #if !defined(APP_XS) run_addressUtilsByron_test(); + #endif run_addressUtilsShelley_test(); - run_txHashBuilder_test(); run_auxDataHashBuilder_test(); + #if defined(APP_FEATURE_NATIVE_SCRIPT_HASH) run_nativeScriptHashBuilder_test(); + #endif PRINTF("All tests done\n"); + } END_ASSERT_NOEXCEPT; io_send_buf(SUCCESS, NULL, 0); diff --git a/src/securityPolicy.c b/src/securityPolicy.c index a694a749..a5ffd4b2 100644 --- a/src/securityPolicy.c +++ b/src/securityPolicy.c @@ -463,7 +463,7 @@ security_policy_t policyForSignTxInput(sign_tx_signingmode_t txSigningMode) static bool is_addressBytes_suitable_for_tx_output( const uint8_t* addressBuffer, size_t addressSize, - const uint8_t networkId, const uint32_t protocolMagic + const uint8_t networkId, const uint32_t protocolMagic __attribute__((unused)) ) { ASSERT(addressSize < BUFFER_SIZE_PARANOIA); @@ -482,7 +482,9 @@ static bool is_addressBytes_suitable_for_tx_output( return false; case BYRON: + #ifdef APP_FEATURE_BYRON_PROTOCOL_MAGIC_CHECK CHECK(extractProtocolMagic(addressBuffer, addressSize) == protocolMagic); + #endif // APP_FEATURE_BYRON_PROTOCOL_MAGIC_CHECK break; default: { @@ -1091,6 +1093,8 @@ security_policy_t policyForSignTxCertificateStaking( DENY(); // should not be reached } +#ifdef APP_FEATURE_POOL_RETIREMENT + security_policy_t policyForSignTxCertificateStakePoolRetirement( sign_tx_signingmode_t txSigningMode, const bip44_path_t* poolIdPath, @@ -1115,6 +1119,10 @@ security_policy_t policyForSignTxCertificateStakePoolRetirement( DENY(); // should not be reached } +#endif // APP_FEATURE_POOL_RETIREMENT + +#ifdef APP_FEATURE_POOL_REGISTRATION + security_policy_t policyForSignTxStakePoolRegistrationInit( sign_tx_signingmode_t txSigningMode, uint32_t numOwners @@ -1285,6 +1293,8 @@ security_policy_t policyForSignTxStakePoolRegistrationConfirm( ALLOW(); } +#endif // APP_FEATURE_POOL_REGISTRATION + // For each withdrawal security_policy_t policyForSignTxWithdrawal( sign_tx_signingmode_t txSigningMode, @@ -1461,6 +1471,8 @@ static inline security_policy_t _plutusWitnessPolicy(const bip44_path_t* path, b } } +#ifdef APP_FEATURE_POOL_REGISTRATION + static inline security_policy_t _poolRegistrationOwnerWitnessPolicy(const bip44_path_t* witnessPath, const bip44_path_t* poolOwnerPath) { switch (bip44_classifyPath(witnessPath)) { @@ -1493,7 +1505,8 @@ static inline security_policy_t _poolRegistrationOperatorWitnessPolicy(const bip case PATH_POOL_COLD_KEY: // only ordinary spending key paths (because of inputs) and pool cold key path are allowed WARN_UNLESS(bip44_isPathReasonable(path)); - // TODO is there a reason to show the witnesses? + // it might be safe to hide the witnesses, but txs related to stake pools + // are rare, so it would not help much and might introduce some unknown risk SHOW(); break; @@ -1503,6 +1516,8 @@ static inline security_policy_t _poolRegistrationOperatorWitnessPolicy(const bip } } +#endif // APP_FEATURE_POOL_REGISTRATION + // For each transaction witness // Note: witnesses reveal public key of an address and Ledger *does not* check // whether they correspond to previously declared inputs and certificates @@ -1510,7 +1525,7 @@ security_policy_t policyForSignTxWitness( sign_tx_signingmode_t txSigningMode, const bip44_path_t* witnessPath, bool mintPresent, - const bip44_path_t* poolOwnerPath + const bip44_path_t* poolOwnerPath __attribute__((unused)) ) { switch (txSigningMode) { @@ -1523,12 +1538,16 @@ security_policy_t policyForSignTxWitness( case SIGN_TX_SIGNINGMODE_PLUTUS_TX: return _plutusWitnessPolicy(witnessPath, mintPresent); + #ifdef APP_FEATURE_POOL_REGISTRATION + case SIGN_TX_SIGNINGMODE_POOL_REGISTRATION_OWNER: return _poolRegistrationOwnerWitnessPolicy(witnessPath, poolOwnerPath); case SIGN_TX_SIGNINGMODE_POOL_REGISTRATION_OPERATOR: return _poolRegistrationOperatorWitnessPolicy(witnessPath); + #endif // APP_FEATURE_POOL_REGISTRATION + default: ASSERT(false); } @@ -1852,6 +1871,7 @@ security_policy_t policyForCVoteRegistrationConfirm() PROMPT(); } +#ifdef APP_FEATURE_OPCERT security_policy_t policyForSignOpCert(const bip44_path_t* poolColdKeyPathSpec) { switch (bip44_classifyPath(poolColdKeyPathSpec)) { @@ -1871,6 +1891,7 @@ security_policy_t policyForSignOpCert(const bip44_path_t* poolColdKeyPathSpec) DENY(); // should not be reached } +#endif // APP_FEATURE_OPCERT security_policy_t policyForSignCVoteInit() { diff --git a/src/securityPolicy.h b/src/securityPolicy.h index 37613d7c..299c4298 100644 --- a/src/securityPolicy.h +++ b/src/securityPolicy.h @@ -113,11 +113,14 @@ security_policy_t policyForSignTxCertificateStaking( const certificate_type_t certificateType, const stake_credential_t* stakeCredential ); +#ifdef APP_FEATURE_POOL_RETIREMENT security_policy_t policyForSignTxCertificateStakePoolRetirement( sign_tx_signingmode_t txSigningMode, const bip44_path_t* stakeCredential, uint64_t epoch ); +#endif // APP_FEATURE_POOL_RETIREMENT +#ifdef APP_FEATURE_POOL_REGISTRATION security_policy_t policyForSignTxStakePoolRegistrationInit( sign_tx_signingmode_t txSigningMode, uint32_t numOwners @@ -147,7 +150,7 @@ security_policy_t policyForSignTxStakePoolRegistrationNoMetadata(); security_policy_t policyForSignTxStakePoolRegistrationConfirm( uint32_t numOwners, uint32_t numRelays ); - +#endif // APP_FEATURE_POOL_REGISTRATION security_policy_t policyForSignTxWithdrawal( sign_tx_signingmode_t txSigningMode, const stake_credential_t* stakeCredential @@ -185,7 +188,9 @@ security_policy_t policyForSignTxReferenceInput(const sign_tx_signingmode_t txSi security_policy_t policyForSignTxConfirm(); +#ifdef APP_FEATURE_OPCERT security_policy_t policyForSignOpCert(const bip44_path_t* poolColdKeyPathSpec); +#endif // APP_FEATURE_OPCERT security_policy_t policyForCVoteRegistrationVoteKey(); security_policy_t policyForCVoteRegistrationVoteKeyPath( diff --git a/src/signOpCert.c b/src/signOpCert.c index 9a3302b4..b28e820c 100644 --- a/src/signOpCert.c +++ b/src/signOpCert.c @@ -1,3 +1,5 @@ +#ifdef APP_FEATURE_OPCERT + #include "common.h" #include "signOpCert.h" @@ -243,3 +245,5 @@ static void signOpCert_ui_runStep() } UI_STEP_END(UI_STEP_INVALID); } + +#endif // APP_FEATURE_OPCERT diff --git a/src/signOpCert.h b/src/signOpCert.h index af844792..e88eec68 100644 --- a/src/signOpCert.h +++ b/src/signOpCert.h @@ -1,6 +1,8 @@ #ifndef H_CARDANO_APP_SIGN_OP_CERT #define H_CARDANO_APP_SIGN_OP_CERT +#ifdef APP_FEATURE_OPCERT + #include "common.h" #include "handlers.h" #include "bip44.h" @@ -20,4 +22,6 @@ typedef struct { int ui_step; } ins_sign_op_cert_context_t; +#endif // APP_FEATURE_OPCERT + #endif // H_CARDANO_APP_SIGN_OP_CERT \ No newline at end of file diff --git a/src/signTx.c b/src/signTx.c index f26bec2d..f8efc472 100644 --- a/src/signTx.c +++ b/src/signTx.c @@ -188,10 +188,14 @@ void tx_advanceStage() } ctx->stage = SIGN_STAGE_BODY_MINT; if (ctx->includeMint) { + #ifdef APP_FEATURE_TOKEN_MINTING txHashBuilder_enterMint(&BODY_CTX->txHashBuilder); signTxMint_init(); // wait for mint APDU break; + #else + ASSERT(false); + #endif // APP_FEATURE_TOKEN_MINTING } __attribute__((fallthrough)); @@ -312,7 +316,11 @@ void tx_advanceCertificatesStateIfAppropriate() break; default: + #ifdef APP_FEATURE_POOL_REGISTRATION ASSERT(ctx->stage == SIGN_STAGE_BODY_CERTIFICATES_POOL_SUBMACHINE); + #else + ASSERT(false); + #endif // APP_FEATURE_POOL_REGISTRATION } } @@ -343,6 +351,8 @@ static inline void checkForFinishedSubmachines() } break; + #ifdef APP_FEATURE_POOL_REGISTRATION + case SIGN_STAGE_BODY_CERTIFICATES_POOL_SUBMACHINE: if (signTxPoolRegistration_isFinished()) { TRACE(); @@ -353,6 +363,8 @@ static inline void checkForFinishedSubmachines() } break; + #endif // APP_FEATURE_POOL_REGISTRATION + case SIGN_STAGE_AUX_DATA_CVOTE_REGISTRATION_SUBMACHINE: if (signTxCVoteRegistration_isFinished()) { TRACE(); @@ -367,6 +379,8 @@ static inline void checkForFinishedSubmachines() } break; + #ifdef APP_FEATURE_TOKEN_MINTING + case SIGN_STAGE_BODY_MINT_SUBMACHINE: if (signTxMint_isFinished()) { TRACE(); @@ -376,6 +390,8 @@ static inline void checkForFinishedSubmachines() } break; + #endif // APP_FEATURE_TOKEN_MINTING + case SIGN_STAGE_BODY_COLLATERAL_OUTPUT_SUBMACHINE: if (isCurrentOutputFinished()) { TRACE(); @@ -480,13 +496,19 @@ static void signTx_handleInitAPDU(uint8_t p2, const uint8_t* wireDataBuffer, siz TRACE("Signing mode %d", (int) ctx->commonTxData.txSigningMode); switch (ctx->commonTxData.txSigningMode) { case SIGN_TX_SIGNINGMODE_ORDINARY_TX: - case SIGN_TX_SIGNINGMODE_POOL_REGISTRATION_OWNER: - case SIGN_TX_SIGNINGMODE_POOL_REGISTRATION_OPERATOR: case SIGN_TX_SIGNINGMODE_MULTISIG_TX: case SIGN_TX_SIGNINGMODE_PLUTUS_TX: // these signing modes are allowed break; + case SIGN_TX_SIGNINGMODE_POOL_REGISTRATION_OWNER: + case SIGN_TX_SIGNINGMODE_POOL_REGISTRATION_OPERATOR: + // these are allowed unless we have the XS app which does not have code for handling them + #ifndef APP_FEATURE_POOL_REGISTRATION + THROW(ERR_INVALID_DATA); + #endif // APP_FEATURE_POOL_REGISTRATION + break; + default: THROW(ERR_INVALID_DATA); } @@ -535,6 +557,13 @@ static void signTx_handleInitAPDU(uint8_t p2, const uint8_t* wireDataBuffer, siz ctx->shouldDisplayTxid = false; } + // minting not included in the XS app + #ifndef APP_FEATURE_TOKEN_MINTING + if (ctx->includeMint) { + THROW(ERR_INVALID_DATA); + } + #endif // APP_FEATURE_TOKEN_MINTING + security_policy_t policy = policyForSignTxInit( ctx->commonTxData.txSigningMode, ctx->commonTxData.networkId, @@ -925,16 +954,24 @@ static void _parseCertificateData(const uint8_t* wireDataBuffer, size_t wireData view_parseBuffer(certificateData->poolKeyHash, &view, POOL_KEY_HASH_LENGTH); break; + #ifdef APP_FEATURE_POOL_REGISTRATION + case CERTIFICATE_TYPE_STAKE_POOL_REGISTRATION: // nothing more to parse, certificate data will be provided // in additional APDUs processed by a submachine return; + #endif // APP_FEATURE_POOL_REGISTRATION + + #ifdef APP_FEATURE_POOL_RETIREMENT + case CERTIFICATE_TYPE_STAKE_POOL_RETIREMENT: _parsePathSpec(&view, &certificateData->poolIdPath); certificateData->epoch = parse_u8be(&view); break; + #endif // APP_FEATURE_POOL_RETIREMENT + default: THROW(ERR_INVALID_DATA); } @@ -1016,6 +1053,8 @@ static void _addCertificateDataToTx( break; } + #ifdef APP_FEATURE_POOL_RETIREMENT + case CERTIFICATE_TYPE_STAKE_POOL_RETIREMENT: { _fillHashFromPath(&BODY_CTX->stageData.certificate.poolIdPath, certificateData->poolKeyHash, SIZEOF(certificateData->poolKeyHash)); txHashBuilder_addCertificate_poolRetirement( @@ -1026,6 +1065,8 @@ static void _addCertificateDataToTx( break; } + #endif // APP_FEATURE_POOL_RETIREMENT + default: ASSERT(false); } @@ -1038,6 +1079,7 @@ static void signTx_handleCertificateAPDU(uint8_t p2, const uint8_t* wireDataBuff ASSERT(wireDataSize < BUFFER_SIZE_PARANOIA); ASSERT(BODY_CTX->currentCertificate < ctx->numCertificates); + #ifdef APP_FEATURE_POOL_REGISTRATION // delegate to state sub-machine for stake pool registration certificate data if (signTxPoolRegistration_isValidInstruction(p2)) { TRACE(); @@ -1048,6 +1090,7 @@ static void signTx_handleCertificateAPDU(uint8_t p2, const uint8_t* wireDataBuff signTxPoolRegistration_handleAPDU(p2, wireDataBuffer, wireDataSize); return; } + #endif // APP_FEATURE_POOL_REGISTRATION VALIDATE(p2 == P2_UNUSED, ERR_INVALID_REQUEST_PARAMETERS); CHECK_STAGE(SIGN_STAGE_BODY_CERTIFICATES); @@ -1097,6 +1140,8 @@ static void signTx_handleCertificateAPDU(uint8_t p2, const uint8_t* wireDataBuff return; } + #ifdef APP_FEATURE_POOL_REGISTRATION + case CERTIFICATE_TYPE_STAKE_POOL_REGISTRATION: { // pool registration certificates have a separate sub-machine for handling APDU and UI // nothing more to be done with them here, we just init the sub-machine @@ -1107,6 +1152,10 @@ static void signTx_handleCertificateAPDU(uint8_t p2, const uint8_t* wireDataBuff return; } + #endif // APP_FEATURE_POOL_REGISTRATION + + #ifdef APP_FEATURE_POOL_RETIREMENT + case CERTIFICATE_TYPE_STAKE_POOL_RETIREMENT: { security_policy_t policy = policyForSignTxCertificateStakePoolRetirement( ctx->commonTxData.txSigningMode, @@ -1130,6 +1179,8 @@ static void signTx_handleCertificateAPDU(uint8_t p2, const uint8_t* wireDataBuff return; } + #endif // APP_FEATURE_POOL_RETIREMENT + default: ASSERT(false); } @@ -1305,6 +1356,8 @@ static void signTx_handleValidityIntervalStartAPDU(uint8_t p2, const uint8_t* wi // ============================== MINT ============================== +#ifdef APP_FEATURE_TOKEN_MINTING + static void signTx_handleMintAPDU(uint8_t p2, const uint8_t* wireDataBuffer, size_t wireDataSize) { { @@ -1324,6 +1377,8 @@ static void signTx_handleMintAPDU(uint8_t p2, const uint8_t* wireDataBuffer, siz signTxMint_handleAPDU(p2, wireDataBuffer, wireDataSize); } +#endif // APP_FEATURE_TOKEN_MINTING + // ========================= SCRIPT DATA HASH ========================== static void signTx_handleScriptDataHashAPDU(uint8_t p2, const uint8_t* wireDataBuffer, size_t wireDataSize) @@ -1778,11 +1833,13 @@ static subhandler_fn_t* lookup_subhandler(uint8_t p1) CASE(0x06, signTx_handleCertificateAPDU); CASE(0x07, signTx_handleWithdrawalAPDU); CASE(0x09, signTx_handleValidityIntervalStartAPDU); + #ifdef APP_FEATURE_TOKEN_MINTING CASE(0x0b, signTx_handleMintAPDU); + #endif // APP_FEATURE_TOKEN_MINTING CASE(0x0c, signTx_handleScriptDataHashAPDU); CASE(0x0d, signTx_handleCollateralInputAPDU); CASE(0x0e, signTx_handleRequiredSignerAPDU); - CASE(0x12, signTx_handleCollateralOutputAPDU); // TODO perhaps change the numbers for the newly added items? + CASE(0x12, signTx_handleCollateralOutputAPDU); CASE(0x10, signTx_handleTotalCollateralAPDU); CASE(0x11, signTx_handleReferenceInputsAPDU); CASE(0x0a, signTx_handleConfirmAPDU); @@ -1819,11 +1876,15 @@ void signTx_handleAPDU( case SIGN_STAGE_BODY_FEE: case SIGN_STAGE_BODY_TTL: case SIGN_STAGE_BODY_CERTIFICATES: + #ifdef APP_FEATURE_POOL_REGISTRATION case SIGN_STAGE_BODY_CERTIFICATES_POOL_SUBMACHINE: + #endif // APP_FEATURE_POOL_REGISTRATION case SIGN_STAGE_BODY_WITHDRAWALS: case SIGN_STAGE_BODY_VALIDITY_INTERVAL: case SIGN_STAGE_BODY_MINT: + #ifdef APP_FEATURE_TOKEN_MINTING case SIGN_STAGE_BODY_MINT_SUBMACHINE: + #endif // APP_FEATURE_TOKEN_MINTING case SIGN_STAGE_BODY_SCRIPT_DATA_HASH: case SIGN_STAGE_BODY_COLLATERAL_INPUTS: case SIGN_STAGE_BODY_REQUIRED_SIGNERS: @@ -1869,11 +1930,15 @@ ins_sign_tx_body_context_t* accessBodyContext() case SIGN_STAGE_BODY_FEE: case SIGN_STAGE_BODY_TTL: case SIGN_STAGE_BODY_CERTIFICATES: + #ifdef APP_FEATURE_POOL_REGISTRATION case SIGN_STAGE_BODY_CERTIFICATES_POOL_SUBMACHINE: + #endif // APP_FEATURE_POOL_REGISTRATION case SIGN_STAGE_BODY_WITHDRAWALS: case SIGN_STAGE_BODY_VALIDITY_INTERVAL: case SIGN_STAGE_BODY_MINT: + #ifdef APP_FEATURE_TOKEN_MINTING case SIGN_STAGE_BODY_MINT_SUBMACHINE: + #endif // APP_FEATURE_TOKEN_MINTING case SIGN_STAGE_BODY_SCRIPT_DATA_HASH: case SIGN_STAGE_BODY_COLLATERAL_INPUTS: case SIGN_STAGE_BODY_REQUIRED_SIGNERS: diff --git a/src/signTx.h b/src/signTx.h index 32a8751b..aa3d8555 100644 --- a/src/signTx.h +++ b/src/signTx.h @@ -33,11 +33,15 @@ typedef enum { SIGN_STAGE_BODY_FEE = 29, SIGN_STAGE_BODY_TTL = 30, SIGN_STAGE_BODY_CERTIFICATES = 31, + #ifdef APP_FEATURE_POOL_REGISTRATION SIGN_STAGE_BODY_CERTIFICATES_POOL_SUBMACHINE = 32, // pool registration certificate sub-machine + #endif // APP_FEATURE_POOL_REGISTRATION SIGN_STAGE_BODY_WITHDRAWALS = 33, SIGN_STAGE_BODY_VALIDITY_INTERVAL = 34, SIGN_STAGE_BODY_MINT = 35, + #ifdef APP_FEATURE_TOKEN_MINTING SIGN_STAGE_BODY_MINT_SUBMACHINE = 36, + #endif // APP_FEATURE_TOKEN_MINTING SIGN_STAGE_BODY_SCRIPT_DATA_HASH = 37, SIGN_STAGE_BODY_COLLATERAL_INPUTS = 38, SIGN_STAGE_BODY_REQUIRED_SIGNERS = 39, @@ -169,12 +173,16 @@ typedef struct { uint8_t scriptDataHash[SCRIPT_DATA_HASH_LENGTH]; sign_tx_required_signer_t requiredSigner; uint64_t totalCollateral; - } stageData; // TODO rename to reflect single-APDU scope + } stageData; union { + #ifdef APP_FEATURE_POOL_REGISTRATION pool_registration_context_t pool_registration_subctx; + #endif // APP_FEATURE_POOL_REGISTRATION output_context_t output_subctx; + #ifdef APP_FEATURE_TOKEN_MINTING mint_context_t mint_subctx; + #endif // APP_FEATURE_TOKEN_MINTING } stageContext; } ins_sign_tx_body_context_t; diff --git a/src/signTxMint.c b/src/signTxMint.c index 589b499b..88ca8bc5 100644 --- a/src/signTxMint.c +++ b/src/signTxMint.c @@ -1,3 +1,5 @@ +#ifdef APP_FEATURE_TOKEN_MINTING + #include "signTxMint.h" #include "signTxMint_ui.h" #include "signTxUtils.h" @@ -290,3 +292,5 @@ bool signTxMint_isFinished() ASSERT(false); } } + +#endif // APP_FEATURE_TOKEN_MINTING diff --git a/src/signTxMint.h b/src/signTxMint.h index 97958082..51389107 100644 --- a/src/signTxMint.h +++ b/src/signTxMint.h @@ -1,6 +1,8 @@ #ifndef H_CARDANO_APP_SIGN_TX_MINT #define H_CARDANO_APP_SIGN_TX_MINT +#ifdef APP_FEATURE_TOKEN_MINTING + #include "common.h" #include "cardano.h" #include "addressUtilsShelley.h" @@ -55,4 +57,6 @@ void signTxMint_handleAPDU(uint8_t p2, const uint8_t* wireDataBuffer, size_t wir bool signTxMint_isFinished(); +#endif // APP_FEATURE_TOKEN_MINTING + #endif // H_CARDANO_APP_SIGN_TX_MINT diff --git a/src/signTxMint_ui.c b/src/signTxMint_ui.c index 5638b5e8..456871ec 100644 --- a/src/signTxMint_ui.c +++ b/src/signTxMint_ui.c @@ -1,3 +1,5 @@ +#ifdef APP_FEATURE_TOKEN_MINTING + #include "signTxMint.h" #include "signTxMint_ui.h" #include "signTxUtils.h" @@ -203,3 +205,5 @@ void signTxMint_handleConfirm_ui_runStep() } UI_STEP_END(HANDLE_CONFIRM_STEP_INVALID); } + +#endif // APP_FEATURE_TOKEN_MINTING \ No newline at end of file diff --git a/src/signTxMint_ui.h b/src/signTxMint_ui.h index be87f434..58f5aeaf 100644 --- a/src/signTxMint_ui.h +++ b/src/signTxMint_ui.h @@ -1,6 +1,8 @@ #ifndef H_CARDANO_APP_SIGN_TX_MINT_UI #define H_CARDANO_APP_SIGN_TX_MINT_UI +#ifdef APP_FEATURE_TOKEN_MINTING + enum { HANDLE_MINT_TOP_LEVEL_DATA_DISPLAY = 9200, HANDLE_MINT_TOP_LEVEL_DATA_RESPOND, @@ -34,4 +36,6 @@ enum { void signTxMint_handleConfirm_ui_runStep(); +#endif // APP_FEATURE_TOKEN_MINTING + #endif // H_CARDANO_APP_SIGN_TX_MINT_UI diff --git a/src/signTxPoolRegistration.c b/src/signTxPoolRegistration.c index 80fc4935..d66f6f81 100644 --- a/src/signTxPoolRegistration.c +++ b/src/signTxPoolRegistration.c @@ -1,3 +1,5 @@ +#ifdef APP_FEATURE_POOL_REGISTRATION + #include "signTx.h" #include "signTxPoolRegistration_ui.h" #include "state.h" @@ -969,3 +971,5 @@ void signTxPoolRegistration_handleAPDU(uint8_t p2, const uint8_t* wireDataBuffer ASSERT(false); } } + +#endif // APP_FEATURE_POOL_REGISTRATION diff --git a/src/signTxPoolRegistration.h b/src/signTxPoolRegistration.h index 7363147b..85504acb 100644 --- a/src/signTxPoolRegistration.h +++ b/src/signTxPoolRegistration.h @@ -1,6 +1,8 @@ #ifndef H_CARDANO_APP_SIGN_TX_POOL_REGISTRATION #define H_CARDANO_APP_SIGN_TX_POOL_REGISTRATION +#ifdef APP_FEATURE_POOL_REGISTRATION + #include "common.h" #include "cardano.h" #include "txHashBuilder.h" @@ -83,4 +85,6 @@ void signTxPoolRegistration_handleAPDU(uint8_t p2, const uint8_t* wireDataBuffer bool signTxPoolRegistration_isFinished(); +#endif // APP_FEATURE_POOL_REGISTRATION + #endif // H_CARDANO_APP_SIGN_TX_POOL_REGISTRATION diff --git a/src/signTxPoolRegistration_ui.c b/src/signTxPoolRegistration_ui.c index 04ece815..855d840b 100644 --- a/src/signTxPoolRegistration_ui.c +++ b/src/signTxPoolRegistration_ui.c @@ -1,3 +1,5 @@ +#ifdef APP_FEATURE_POOL_REGISTRATION + #include "signTx.h" #include "signTxPoolRegistration_ui.h" #include "state.h" @@ -792,3 +794,5 @@ void signTxPoolRegistration_handleConfirm_ui_runStep() } UI_STEP_END(HANDLE_CONFIRM_STEP_INVALID); } + +#endif // APP_FEATURE_POOL_REGISTRATION diff --git a/src/signTxPoolRegistration_ui.h b/src/signTxPoolRegistration_ui.h index b155805f..33575a62 100644 --- a/src/signTxPoolRegistration_ui.h +++ b/src/signTxPoolRegistration_ui.h @@ -1,5 +1,7 @@ -#ifndef H_CARDANO_APP_SIGN_TX_POOL_REGISATRATION_UI -#define H_CARDANO_APP_SIGN_TX_POOL_REGISATRATION_UI +#ifndef H_CARDANO_APP_SIGN_TX_POOL_REGISTRATION_UI +#define H_CARDANO_APP_SIGN_TX_POOL_REGISTRATION_UI + +#ifdef APP_FEATURE_POOL_REGISTRATION // ============================== INIT ============================== @@ -122,4 +124,7 @@ enum { }; void signTxPoolRegistration_handleConfirm_ui_runStep(); -#endif // H_CARDANO_APP_SIGN_TX_POOL_REGISATRATION_UI + +#endif // APP_FEATURE_POOL_REGISTRATION + +#endif // H_CARDANO_APP_SIGN_TX_POOL_REGISTRATION_UI diff --git a/src/signTxUtils.c b/src/signTxUtils.c index 811c506d..ff046edc 100644 --- a/src/signTxUtils.c +++ b/src/signTxUtils.c @@ -1,4 +1,4 @@ -#include "io.h" +#include "cardano_io.h" #include "errors.h" #include "uiHelpers.h" #include "utils.h" diff --git a/src/signTxUtils.h b/src/signTxUtils.h index 8f5baf3f..fcb63149 100644 --- a/src/signTxUtils.h +++ b/src/signTxUtils.h @@ -18,4 +18,4 @@ bool violatesSingleAccountOrStoreIt(const bip44_path_t* path); void view_parseDestination(read_view_t* view, tx_output_destination_storage_t* destination); -#endif // H_CARDANO_APP_SIGN_TX_UTILS +#endif // H_CARDANO_APP_SIGN_TX_UTILS diff --git a/src/signTx_ui.c b/src/signTx_ui.c index 97b71c73..91c00b91 100644 --- a/src/signTx_ui.c +++ b/src/signTx_ui.c @@ -74,12 +74,17 @@ static const char* _newTxLine1(sign_tx_signingmode_t txSigningMode) #ifdef HAVE_NBGL static void signTx_handleInit_ui_runStep_cb(void) { + // if the protocol magic check is not enabled, + // displaying the protocol magic might be misleading, + // so we must not show it + #ifdef APP_FEATURE_BYRON_PROTOCOL_MAGIC_CHECK char networkParams[100] = {0}; ui_getNetworkParamsScreen_2( networkParams, SIZEOF(networkParams), ctx->commonTxData.protocolMagic); fill_and_display_if_required("Protocol magic", networkParams, signTx_handleInit_ui_runStep, respond_with_user_reject); + #endif } #endif // HAVE_NBGL @@ -118,7 +123,8 @@ void signTx_handleInit_ui_runStep() #ifdef HAVE_BAGL ui_displayNetworkParamsScreen( "Network details", - ctx->commonTxData.networkId, ctx->commonTxData.protocolMagic, + ctx->commonTxData.networkId, + ctx->commonTxData.protocolMagic, this_fn ); #elif defined(HAVE_NBGL) @@ -518,6 +524,8 @@ void signTx_handleCertificate_ui_runStep() UI_STEP_END(HANDLE_CERTIFICATE_STEP_INVALID); } +#ifdef APP_FEATURE_POOL_RETIREMENT + void signTx_handleCertificatePoolRetirement_ui_runStep() { TRACE("UI step %d", ctx->ui_step); @@ -579,6 +587,8 @@ void signTx_handleCertificatePoolRetirement_ui_runStep() UI_STEP_END(HANDLE_CERTIFICATE_POOL_RETIREMENT_STEP_INVALID); } +#endif // APP_FEATURE_POOL_RETIREMENT + // ============================== WITHDRAWALS ============================== void signTx_handleWithdrawal_ui_runStep() diff --git a/src/state.h b/src/state.h index 8ca7f18a..f95bcb53 100644 --- a/src/state.h +++ b/src/state.h @@ -14,9 +14,13 @@ typedef union { // Here should go states of all instructions ins_get_keys_context_t getKeysContext; ins_derive_address_context_t deriveAddressContext; + #ifdef APP_FEATURE_NATIVE_SCRIPT_HASH ins_derive_native_script_hash_context_t deriveNativeScriptHashContext; + #endif // APP_FEATURE_NATIVE_SCRIPT_HASH ins_sign_tx_context_t signTxContext; + #ifdef APP_FEATURE_OPCERT ins_sign_op_cert_context_t signOpCertContext; + #endif // APP_FEATURE_OPCERT ins_sign_cvote_context_t signCVoteContext; } instructionState_t; diff --git a/src/txHashBuilder.c b/src/txHashBuilder.c index 8c50e1b5..43efdff3 100644 --- a/src/txHashBuilder.c +++ b/src/txHashBuilder.c @@ -537,8 +537,6 @@ void txHashBuilder_addOutput_datum( ASSERT(false); } - //TODO: MAX_DATUM_SIZE?? - // the babbage output format serializes some preliminary stuff if (builder->outputData.serializationFormat == MAP_BABBAGE) { // datum_option = [ 0, $hash32 // 1, data ] @@ -603,8 +601,6 @@ void txHashBuilder_addOutput_datum_inline_chunk( void txHashBuilder_addOutput_referenceScript(tx_hash_builder_t* builder, size_t scriptSize) { - // TODO: MAX_SCRIPT_SIZE?? maybe we don't need to limit it - ASSERT(builder->outputData.includeRefScript); switch (builder->outputState) { @@ -854,6 +850,8 @@ void txHashBuilder_addCertificate_delegation( } } +#ifdef APP_FEATURE_POOL_RETIREMENT + void txHashBuilder_addCertificate_poolRetirement( tx_hash_builder_t* builder, const uint8_t* poolKeyHash, size_t poolKeyHashSize, @@ -886,6 +884,10 @@ void txHashBuilder_addCertificate_poolRetirement( } } +#endif // APP_FEATURE_POOL_RETIREMENT + +#ifdef APP_FEATURE_POOL_REGISTRATION + void txHashBuilder_poolRegistrationCertificate_enter( tx_hash_builder_t* builder, uint16_t numOwners, uint16_t numRelays @@ -1280,6 +1282,8 @@ void txHashBuilder_addPoolRegistrationCertificate_addPoolMetadata_null( builder->state = TX_HASH_BUILDER_IN_CERTIFICATES; } +#endif // APP_FEATURE_POOL_REGISTRATION + static void txHashBuilder_assertCanLeaveCertificates(tx_hash_builder_t* builder) { _TRACE("state = %d, remainingCertificates = %u", builder->state, builder->remainingCertificates); @@ -1434,6 +1438,8 @@ static void txHashBuilder_assertCanLeaveValidityIntervalStart(tx_hash_builder_t* // ============================== MINT ============================== +#ifdef APP_FEATURE_TOKEN_MINTING + void txHashBuilder_enterMint(tx_hash_builder_t* builder) { _TRACE("state = %d", builder->state); @@ -1490,6 +1496,8 @@ void txHashBuilder_addMint_token( amount < 0 ? CBOR_TYPE_NEGATIVE : CBOR_TYPE_UNSIGNED); } +#endif // APP_FEATURE_TOKEN_MINTING + static void txHashBuilder_assertCanLeaveMint(tx_hash_builder_t* builder) { _TRACE("state = %u, remainingMintAssetGroups = %u, remainingMintTokens = %u", diff --git a/src/txHashBuilder.h b/src/txHashBuilder.h index e633bca6..e15de3ea 100644 --- a/src/txHashBuilder.h +++ b/src/txHashBuilder.h @@ -264,12 +264,18 @@ void txHashBuilder_addCertificate_delegation( const uint8_t* poolKeyHash, size_t poolKeyHashSize ); +#ifdef APP_FEATURE_POOL_RETIREMENT + void txHashBuilder_addCertificate_poolRetirement( tx_hash_builder_t* builder, const uint8_t* poolKeyHash, size_t poolKeyHashSize, uint64_t epoch ); +#endif // APP_FEATURE_POOL_RETIREMENT + +#ifdef APP_FEATURE_POOL_REGISTRATION + void txHashBuilder_poolRegistrationCertificate_enter( tx_hash_builder_t* builder, uint16_t numOwners, uint16_t numRelays @@ -320,6 +326,8 @@ void txHashBuilder_addPoolRegistrationCertificate_addPoolMetadata_null( tx_hash_builder_t* builder ); +#endif // APP_FEATURE_POOL_REGISTRATION + void txHashBuilder_enterWithdrawals(tx_hash_builder_t* builder); void txHashBuilder_addWithdrawal( @@ -338,6 +346,8 @@ void txHashBuilder_addValidityIntervalStart( uint64_t validityIntervalStart ); +#ifdef APP_FEATURE_TOKEN_MINTING + void txHashBuilder_enterMint(tx_hash_builder_t* builder); void txHashBuilder_addMint_topLevelData( @@ -356,6 +366,8 @@ void txHashBuilder_addMint_token( int64_t amount ); +#endif // APP_FEATURE_TOKEN_MINTING + void txHashBuilder_addScriptDataHash( tx_hash_builder_t* builder, const uint8_t* scriptHashData, size_t scriptHashDataSize @@ -406,8 +418,4 @@ void txHashBuilder_finalize( ); -#ifdef DEVEL -void run_txHashBuilder_test(); -#endif // DEVEL - #endif // H_CARDANO_APP_TX_HASH_BUILDER diff --git a/src/txHashBuilder_test.c b/src/txHashBuilder_test.c deleted file mode 100644 index 1a0f0a8a..00000000 --- a/src/txHashBuilder_test.c +++ /dev/null @@ -1,565 +0,0 @@ -#ifdef DEVEL - -#include "txHashBuilder.h" -#include "cardano.h" -#include "hexUtils.h" -#include "textUtils.h" -#include "testUtils.h" - - -static const struct { - const char* txHashHex; - int index; -} inputs[] = { - { - "0B40265111D8BB3C3C608D95B3A0BF83461ACE32D79336579A1939B3AAD1C0B7", - 0 - }, - { - "1B40265111D8BB3C3C608D95B3A0BF83461ACE32D79336579A1939B3AAD1C0B7", - 1 - }, - { - "2B40265111D8BB3C3C608D95B3A0BF83461ACE32D79336579A1939B3AAD1C0B7", - 2 - }, - { - "3B40265111D8BB3C3C608D95B3A0BF83461ACE32D79336579A1939B3AAD1C0B7", - 3 - }, -}; - -static const struct { - const char* rawAddressHex; - uint64_t amount; -} outputs[] = { - { - "82D818582183581C6EE5BB111C8771CE03278E624056A12C9CFB353EB112E8ABF21FA4FEA0001A74EEE408", - 100 - }, - { - "009493315CD92EB5D8C4304E67B7E16AE36D61D34502694657811A2C8E32C728D3861E164CAB28CB8F006448139C8F1740FFB8E7AA9E5232DC", - 200 - }, - { - "409493315CD92EB5D8C4304E67B7E16AE36D61D34502694657811A2C8E87688F509738", - 300 - }, - { - "609493315CD92EB5D8C4304E67B7E16AE36D61D34502694657811A2C8E", - 400 - }, - { - "609493315CD92EB5D8C4304E67B7E16AE36D61D34502694657811A2C8E", - 500 - }, -}; - -static struct { - const char* stakingKeyHash; -} registrationCertificates[] = { - { - "32C728D3861E164CAB28CB8F006448139C8F1740FFB8E7AA9E5232DC" - }, -}; - -static struct { - const char* stakingKeyHash; -} deregistrationCertificates[] = { - { - "32C728D3861E164CAB28CB8F006448139C8F1740FFB8E7AA9E5232DC" - }, - { - "337B62CFFF6403A06A3ACBC34F8C46003C69FE79A3628CEFA9C47251" - }, -}; - -static struct { - const char* stakingKeyHash; - const char* poolKeyHash; -} delegationCertificates[] = { - { - "32C728D3861E164CAB28CB8F006448139C8F1740FFB8E7AA9E5232DC", - "0D13015CDBCDBD0889CE276192A1601F2D4D20B8392D4EF4F9A754E2" - }, - { - "32C728D3861E164CAB28CB8F006448139C8F1740FFB8E7AA9E5232DC", - "1D13015CDBCDBD0889CE276192A1601F2D4D20B8392D4EF4F9A754E2" - }, - { - "32C728D3861E164CAB28CB8F006448139C8F1740FFB8E7AA9E5232DC", - "2D13015CDBCDBD0889CE276192A1601F2D4D20B8392D4EF4F9A754E2" - }, -}; - -static struct { - const char* rewardAddress; - uint64_t amount; -} withdrawals[] = { - { - "E032C728D3861E164CAB28CB8F006448139C8F1740FFB8E7AA9E5232DC", - 666 - } -}; - -static const char* expectedHex = "7d772be6f4bebee00b469ca2793b3636594a9b16267cf23ae40236065387b3f0"; -static const char* scriptDataHash = "853cbe68f7fccdeeeb0fd7b711ea147912190c35ac52d9d94080ae82809b2f84"; - -typedef void(*addTokenGroupFun)(tx_hash_builder_t* builder, - const uint8_t* policyIdBuffer, size_t policyIdSize, - uint16_t numTokens); -typedef void(*addTokenFun)(tx_hash_builder_t* builder, - const uint8_t* assetNameBuffer, size_t assetNameSize, - uint64_t amount); - -static void addTwoMultiassetTokenGroups(tx_hash_builder_t* builder, - addTokenGroupFun tokenGroupAdder, addTokenFun tokenAdder) -{ - // we reuse the buffers to avoid wasting stack - uint8_t policy[MINTING_POLICY_ID_SIZE] = {0}; - explicit_bzero(policy, SIZEOF(policy)); - - uint8_t assetNameBuffer[ASSET_NAME_SIZE_MAX] = {0}; - explicit_bzero(assetNameBuffer, SIZEOF(assetNameBuffer)); - - policy[0] = 1; - tokenGroupAdder(builder, policy, SIZEOF(policy), 2); - - assetNameBuffer[0] = 11; - tokenAdder(builder, assetNameBuffer, SIZEOF(assetNameBuffer), 110); - assetNameBuffer[0] = 12; - tokenAdder(builder, assetNameBuffer, SIZEOF(assetNameBuffer), 120); - - policy[0] = 2; - tokenGroupAdder(builder, policy, SIZEOF(policy), 2); - - assetNameBuffer[0] = 21; - tokenAdder(builder, assetNameBuffer, SIZEOF(assetNameBuffer), 210); - assetNameBuffer[0] = 22; - // use a short buffer on purpose - tokenAdder(builder, assetNameBuffer, 1, 220); -} - -static void mintTokenHandler(tx_hash_builder_t* builder, - const uint8_t* assetNameBuffer, size_t assetNameSize, - uint64_t amount) -{ - txHashBuilder_addMint_token(builder, assetNameBuffer, assetNameSize, (int64_t)amount); -} - -static void addMultiassetMint(tx_hash_builder_t* builder) -{ - txHashBuilder_addMint_topLevelData(builder, 2); - addTwoMultiassetTokenGroups(builder, &txHashBuilder_addMint_tokenGroup, &mintTokenHandler); -} - -static void addMint(tx_hash_builder_t* builder) -{ - txHashBuilder_enterMint(builder); - - addMultiassetMint(builder); -} - -static void outputTokenHandler( - tx_hash_builder_t* builder, - const uint8_t* assetNameBuffer, size_t assetNameSize, - uint64_t amount -) -{ - txHashBuilder_addOutput_token(builder, assetNameBuffer, assetNameSize, amount); -} - - -static void addMultiassetOutput(tx_hash_builder_t* builder, tx_output_serialization_format_t const* outputFormat) -{ - uint8_t tmp[70] = {0}; - size_t tmpSize = decode_hex(PTR_PIC(outputs[1].rawAddressHex), tmp, SIZEOF(tmp)); - tx_output_description_t output = { - .format = (*outputFormat), - .destination = { - .type = DESTINATION_THIRD_PARTY, - .address = { - .buffer = tmp, - .size = tmpSize, - }, - }, - .amount = outputs[1].amount, - .numAssetGroups = 2, - .includeDatum = false, - .includeRefScript = false - }; - txHashBuilder_addOutput_topLevelData(builder, &output); - - addTwoMultiassetTokenGroups(builder, &txHashBuilder_addOutput_tokenGroup, &outputTokenHandler); -} - -static void addOutputs(tx_hash_builder_t* builder) -{ - txHashBuilder_enterOutputs(builder); - - tx_output_serialization_format_t outputFormat = ARRAY_LEGACY; - addMultiassetOutput(builder, &outputFormat); - - ITERATE(it, outputs) { - uint8_t tmp[70] = {0}; - size_t tmpSize = decode_hex(PTR_PIC(it->rawAddressHex), tmp, SIZEOF(tmp)); - tx_output_description_t output = { - .format = outputFormat, - .destination = { - .type = DESTINATION_THIRD_PARTY, - .address = { - .size = tmpSize, - .buffer = tmp, - } - }, - .amount = it->amount, - .numAssetGroups = 0, - .includeDatum = false, - .includeRefScript = false - }; - txHashBuilder_addOutput_topLevelData( - builder, - &output - ); - } - - // added for the second time to more thoroughly check the state machine - addMultiassetOutput(builder, &outputFormat); - - //New output format - outputFormat = MAP_BABBAGE; - - addMultiassetOutput(builder, &outputFormat); - - ITERATE(it, outputs) { - uint8_t tmp[70] = {0}; - size_t tmpSize = decode_hex(PTR_PIC(it->rawAddressHex), tmp, SIZEOF(tmp)); - - tx_output_description_t output = { - .format = outputFormat, - .destination = { - .type = DESTINATION_THIRD_PARTY, - .address = { - .buffer = tmp, - .size = tmpSize, - }, - }, - .amount = it->amount, - .numAssetGroups = 0, - .includeDatum = false, - .includeRefScript = false - }; - txHashBuilder_addOutput_topLevelData(builder, &output); - } - - // added for the second time to more thoroughly check the state machine - addMultiassetOutput(builder, &outputFormat); -} - -static void collateralOutputTokenHandler(tx_hash_builder_t* builder, - const uint8_t* assetNameBuffer, size_t assetNameSize, - uint64_t amount) -{ - txHashBuilder_addCollateralOutput_token(builder, assetNameBuffer, assetNameSize, (int64_t)amount); -} -//TODO: more generic function to handle similar? or just merge to addCollRet? -static void addMultiassetCollateralOutput(tx_hash_builder_t* builder, tx_output_serialization_format_t outputFormat) -{ - uint8_t tmp[70] = {0}; - size_t tmpSize = decode_hex(PTR_PIC(outputs[1].rawAddressHex), tmp, SIZEOF(tmp)); - tx_output_description_t output = { - .format = outputFormat, - .destination = { - .type = DESTINATION_THIRD_PARTY, - .address = { - .buffer = tmp, - .size = tmpSize, - }, - }, - .amount = outputs[1].amount, - .numAssetGroups = 2, - .includeDatum = false, - .includeRefScript = false - }; - txHashBuilder_addCollateralOutput(builder, &output); - - addTwoMultiassetTokenGroups(builder, &txHashBuilder_addCollateralOutput_tokenGroup, &collateralOutputTokenHandler); -} - -static void addCollateralOutput(tx_hash_builder_t* builder) -{ - addMultiassetCollateralOutput(builder, MAP_BABBAGE); -} - -static void addPoolRegistrationCertificate(tx_hash_builder_t* builder) -{ - uint8_t poolKeyHash[POOL_KEY_HASH_LENGTH] = {0}; - uint8_t vrfKeyHash[VRF_KEY_HASH_LENGTH] = {0}; - uint64_t pledge = 500000000; - uint64_t cost = 340000000; - uint64_t marginNumerator = 1; - uint64_t marginDenominator = 1; - uint8_t rewardAccount[REWARD_ACCOUNT_SIZE] = {0}; - - size_t poolKeyHashSize = decode_hex( - "5631EDE662CFB10FD5FD69B4667101DD289568E12BCF5F64D1C406FC", - poolKeyHash, SIZEOF(poolKeyHash) - ); - ASSERT(poolKeyHashSize == SIZEOF(poolKeyHash)); - - size_t vrfKeyHashSize = decode_hex( - "198890AD6C92E80FBDAB554DDA02DA9FB49D001BBD96181F3E07F7A6AB0D0640", - vrfKeyHash, SIZEOF(vrfKeyHash) - ); - ASSERT(vrfKeyHashSize == SIZEOF(vrfKeyHash)); - - size_t rewardAccountSize = decode_hex( - "E03A7F09D3DF4CF66A7399C2B05BFA234D5A29560C311FC5DB4C490711", - rewardAccount, SIZEOF(rewardAccount) - ); - ASSERT(rewardAccountSize == SIZEOF(rewardAccount)); - - txHashBuilder_poolRegistrationCertificate_enter(builder, 1, 3); - txHashBuilder_poolRegistrationCertificate_poolKeyHash(builder, poolKeyHash, SIZEOF(poolKeyHash)); - txHashBuilder_poolRegistrationCertificate_vrfKeyHash(builder, vrfKeyHash, SIZEOF(vrfKeyHash)); - txHashBuilder_poolRegistrationCertificate_financials(builder, pledge, cost, marginNumerator, marginDenominator); - txHashBuilder_poolRegistrationCertificate_rewardAccount(builder, rewardAccount, SIZEOF(rewardAccount)); - - txHashBuilder_addPoolRegistrationCertificate_enterOwners(builder); - - uint8_t owner1[28] = {0}; - size_t owner1Size = decode_hex("3A7F09D3DF4CF66A7399C2B05BFA234D5A29560C311FC5DB4C490711", owner1, SIZEOF(owner1)); - ASSERT(owner1Size == SIZEOF(owner1)); - - txHashBuilder_addPoolRegistrationCertificate_addOwner(builder, owner1, owner1Size); - - txHashBuilder_addPoolRegistrationCertificate_enterRelays(builder); - - { - pool_relay_t relay0; - relay0.format = 0; - relay0.port.isNull = false; - relay0.port.number = 1234; - relay0.ipv4.isNull = false; - decode_hex("08080808", relay0.ipv4.ip, IPV4_SIZE); - relay0.ipv6.isNull = true; - txHashBuilder_addPoolRegistrationCertificate_addRelay(builder, &relay0); - } - { - pool_relay_t relay1; - relay1.format = 1; - relay1.port.isNull = true; - // a valid DNS AAAA record, since dnsName actually is supposed to be an A or AAAA record - const char* dnsName = "AAAA 2400:cb00:2049:1::a29f:1804"; - relay1.dnsNameSize = str_textToBuffer(dnsName, relay1.dnsName, SIZEOF(relay1.dnsName)); - txHashBuilder_addPoolRegistrationCertificate_addRelay(builder, &relay1); - } - { - pool_relay_t relay2; - relay2.format = 2; - // dnsName is not a valid DNS SRV record, but we don't validate it - const char* dnsName = "AAAA 2400:cb00:2049:1::a29f:1804"; - relay2.dnsNameSize = str_textToBuffer(dnsName, relay2.dnsName, SIZEOF(relay2.dnsName)); - txHashBuilder_addPoolRegistrationCertificate_addRelay(builder, &relay2); - } - - uint8_t metadataHash[32] = {0}; - size_t metadataHashSize = decode_hex("914C57C1F12BBF4A82B12D977D4F274674856A11ED4B9B95BD70F5D41C5064A6", metadataHash, SIZEOF(metadataHash)); - ASSERT(metadataHashSize == SIZEOF(metadataHash)); - - const char* metadataUrl = "https://teststakepool.com"; - uint8_t urlBuffer[DNS_NAME_SIZE_MAX] = {0}; - size_t urlSize = str_textToBuffer(metadataUrl, urlBuffer, SIZEOF(urlBuffer)); - ASSERT(urlSize <= DNS_NAME_SIZE_MAX); - - txHashBuilder_addPoolRegistrationCertificate_addPoolMetadata(builder, urlBuffer, urlSize, metadataHash, metadataHashSize); -} - -static void addPoolRetirementCertificate(tx_hash_builder_t* builder) -{ - uint8_t poolKeyHash[POOL_KEY_HASH_LENGTH] = {0}; - uint64_t epoch = 1000; - - size_t poolKeyHashSize = decode_hex( - "5631EDE662CFB10FD5FD69B4667101DD289568E12BCF5F64D1C406FC", - poolKeyHash, SIZEOF(poolKeyHash) - ); - ASSERT(poolKeyHashSize == SIZEOF(poolKeyHash)); - - txHashBuilder_addCertificate_poolRetirement( - builder, - poolKeyHash, SIZEOF(poolKeyHash), - epoch - ); -} - -static void addCertificates(tx_hash_builder_t* builder) -{ - txHashBuilder_enterCertificates(builder); - - ITERATE(it, registrationCertificates) { - uint8_t tmp[70] = {0}; - size_t tmpSize = decode_hex(PTR_PIC(it->stakingKeyHash), tmp, SIZEOF(tmp)); - txHashBuilder_addCertificate_stakingHash( - builder, - CERTIFICATE_TYPE_STAKE_REGISTRATION, - STAKE_CREDENTIAL_KEY_PATH, - tmp, tmpSize - ); - } - - ITERATE(it, deregistrationCertificates) { - uint8_t tmp[70] = {0}; - size_t tmpSize = decode_hex(PTR_PIC(it->stakingKeyHash), tmp, SIZEOF(tmp)); - txHashBuilder_addCertificate_stakingHash( - builder, - CERTIFICATE_TYPE_STAKE_DEREGISTRATION, - STAKE_CREDENTIAL_KEY_PATH, - tmp, tmpSize - ); - } - - addPoolRegistrationCertificate(builder); - - addPoolRetirementCertificate(builder); - - ITERATE(it, delegationCertificates) { - uint8_t tmp_credential[70] = {0}; - size_t tmpSize_credential = decode_hex( - PTR_PIC(it->stakingKeyHash), - tmp_credential, SIZEOF(tmp_credential) - ); - uint8_t tmp_pool[70] = {0}; - size_t tmpSize_pool = decode_hex(PTR_PIC(it->poolKeyHash), tmp_pool, SIZEOF(tmp_pool)); - txHashBuilder_addCertificate_delegation( - builder, STAKE_CREDENTIAL_KEY_PATH, - tmp_credential, tmpSize_credential, - tmp_pool, tmpSize_pool - ); - } -} - -void run_txHashBuilder_test() -{ - PRINTF("txHashBuilder test\n"); - tx_hash_builder_t builder; - - const size_t numCertificates = ARRAY_LEN(registrationCertificates) + - ARRAY_LEN(deregistrationCertificates) + - ARRAY_LEN(delegationCertificates) + - 1 + // stake pool retirement certificate - 1; // stake pool registration certificate - - txHashBuilder_init(&builder, - ARRAY_LEN(inputs), - (ARRAY_LEN(outputs) + 2) * 2, // +2 for multiasset outputs *2 for new format - true, // ttl - numCertificates, ARRAY_LEN(withdrawals), - true, // metadata - true, // validity interval start - true, // mint - true, // script hash data - 1, // collateral inputs - 1, // required - true, // network id - true, // collateral return output, - true, // total collateral, - ARRAY_LEN(inputs) // reference inputs - ); - - // 0 : set ; inputs - txHashBuilder_enterInputs(&builder); - ITERATE(it, inputs) { - uint8_t tmp[TX_HASH_LENGTH] = {0}; - size_t tmpSize = decode_hex(PTR_PIC(it->txHashHex), tmp, SIZEOF(tmp)); - tx_input_t input; - memmove(input.txHashBuffer, tmp, tmpSize); - input.index = it->index; - txHashBuilder_addInput(&builder, &input); - } - // 1 : [* transaction_output] - addOutputs(&builder); - // 2 : coin ; fee - txHashBuilder_addFee(&builder, 42); - // ? 3 : uint ; time to live - txHashBuilder_addTtl(&builder, 235000); - // ? 4 : [* certificate] - addCertificates(&builder); - // ? 5 : withdrawals - txHashBuilder_enterWithdrawals(&builder); - - ITERATE(it, withdrawals) { - uint8_t tmp[70] = {0}; - size_t tmpSize = decode_hex(PTR_PIC(it->rewardAddress), tmp, SIZEOF(tmp)); - txHashBuilder_addWithdrawal( - &builder, - tmp, tmpSize, - it->amount - ); - } - // ? 7 : auxiliary_data_hash - { - /* cspell:disable-next-line */ - const char auxDataHashHex[] = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; - uint8_t tmp[AUX_DATA_HASH_LENGTH] = {0}; - size_t tmpSize = decode_hex(auxDataHashHex, tmp, SIZEOF(tmp)); - ASSERT(tmpSize == AUX_DATA_HASH_LENGTH); - txHashBuilder_addAuxData(&builder, tmp, tmpSize); - } - // ? 8 : uint ; validity interval start - txHashBuilder_addValidityIntervalStart(&builder, 33); - // ? 9 : mint - addMint(&builder); - // ? 11 : script_data_hash - { - uint8_t scriptHashData[SCRIPT_DATA_HASH_LENGTH] = {0}; - size_t hashSize = decode_hex(scriptDataHash, scriptHashData, SIZEOF(scriptHashData)); - txHashBuilder_addScriptDataHash(&builder, scriptHashData, hashSize); - } - // ? 13 : set ; collateral inputs - { - txHashBuilder_enterCollateralInputs(&builder); - uint8_t tmp[TX_HASH_LENGTH] = {0}; - size_t tmpSize = decode_hex(PTR_PIC(inputs[0].txHashHex), tmp, SIZEOF(tmp)); - tx_input_t input; - memmove(input.txHashBuffer, tmp, tmpSize); - input.index = inputs[0].index; - txHashBuilder_addCollateralInput(&builder, &input); - } - // ? 14 : required_signers - { - uint8_t keyHash[ADDRESS_KEY_HASH_LENGTH] = {0}; - txHashBuilder_enterRequiredSigners(&builder); - txHashBuilder_addRequiredSigner(&builder, keyHash, SIZEOF(keyHash)); - } - // ? 15 : network_id - txHashBuilder_addNetworkId(&builder, 0); - // ? 16 : transaction_output ; collateral return - addCollateralOutput(&builder); - // ? 17 : coin ; total collateral - txHashBuilder_addTotalCollateral(&builder, 10); - // ? 18 : set ; reference inputs - txHashBuilder_enterReferenceInputs(&builder); - - ITERATE(it, inputs) { - uint8_t tmp[TX_HASH_LENGTH] = {0}; - size_t tmpSize = decode_hex(PTR_PIC(it->txHashHex), tmp, SIZEOF(tmp)); - tx_input_t input; - memmove(input.txHashBuffer, tmp, tmpSize); - input.index = it->index; - txHashBuilder_addReferenceInput(&builder, &input); - } - - uint8_t result[TX_HASH_LENGTH] = {0}; - txHashBuilder_finalize(&builder, result, SIZEOF(result)); - - uint8_t expected[TX_HASH_LENGTH] = {0}; - decode_hex(expectedHex, expected, SIZEOF(expected)); - - PRINTF("result\n"); - PRINTF("%.*h\n", 32, result); - - EXPECT_EQ_BYTES(result, expected, 32); -} - -#endif // DEVEL diff --git a/src/ui.h b/src/ui.h index 0a78cf6e..69139d45 100644 --- a/src/ui.h +++ b/src/ui.h @@ -1,7 +1,7 @@ #ifndef H_CARDANO_APP_UI_H #define H_CARDANO_APP_UI_H -#include "io.h" +#include "cardano_io.h" #include "uiHelpers.h" #ifdef HAVE_NBGL @@ -26,8 +26,4 @@ void display_error(void); void nbgl_reset_transaction_full_context(void); #endif -#ifdef HAVE_BAGL -void io_seproxyhal_display(const bagl_element_t* element); -#endif // HAVE_BAGL - #endif // H_CARDANO_APP_UI_H diff --git a/src/uiHelpers.c b/src/uiHelpers.c index 926d49e1..ff791ef7 100644 --- a/src/uiHelpers.c +++ b/src/uiHelpers.c @@ -3,7 +3,7 @@ #include "uiHelpers.h" #include "uiElements.h" #include "assert.h" -#include "io.h" +#include "cardano_io.h" #include "utils.h" #include "securityPolicy.h" #include "ui.h" @@ -20,8 +20,8 @@ displayState_t displayState; // should never need to reference it directly ux_state_t ux; #elif defined(TARGET_NANOX) || defined(TARGET_NANOS2) || defined(TARGET_STAX) -ux_state_t G_ux; -bolos_ux_params_t G_ux_params; +extern ux_state_t G_ux; +extern bolos_ux_params_t G_ux_params; #endif STATIC_ASSERT(SIZEOF(uint8_t) == SIZEOF(char), "bad char size"); diff --git a/src/uiHelpers_nanos.c b/src/uiHelpers_nanos.c index 2472f138..93b6bc27 100644 --- a/src/uiHelpers_nanos.c +++ b/src/uiHelpers_nanos.c @@ -132,7 +132,7 @@ static const bagl_element_t ui_paginatedText[] = { UI_ICON_LEFT(ID_ICON_GO_LEFT, BAGL_GLYPH_ICON_LEFT), UI_ICON_RIGHT(ID_ICON_GO_RIGHT, BAGL_GLYPH_ICON_RIGHT), - // TODO(ppershing): what are the following magical numbers? + // Note(ppershing): what are the following magical numbers? UI_TEXT(ID_UNSPECIFIED, 0, 12, 128, &displayState.paginatedText.header), UI_TEXT(ID_UNSPECIFIED, 0, 26, 128, &displayState.paginatedText.currentText), diff --git a/src/uiScreens_bagl.c b/src/uiScreens_bagl.c index 1e158a0c..cea937ae 100644 --- a/src/uiScreens_bagl.c +++ b/src/uiScreens_bagl.c @@ -653,11 +653,23 @@ void ui_displayNetworkParamsScreen( STATIC_ASSERT(!IS_SIGNED(networkId), "signed type for %u"); STATIC_ASSERT(sizeof(protocolMagic) <= sizeof(unsigned), "oversized type for %u"); STATIC_ASSERT(!IS_SIGNED(protocolMagic), "signed type for %u"); + + #ifdef APP_FEATURE_BYRON_PROTOCOL_MAGIC_CHECK snprintf( networkParams, SIZEOF(networkParams), "network id %u / protocol magic %u", networkId, protocolMagic ); + #else + // if the protocol magic check is not enabled, + // displaying the protocol magic might be misleading, + // so we must not show it + snprintf( + networkParams, SIZEOF(networkParams), + "network id %u", + networkId + ); + #endif // APP_FEATURE_BYRON_PROTOCOL_MAGIC_CHECK ASSERT(strlen(networkParams) + 1 < SIZEOF(networkParams)); ui_displayPaginatedText( @@ -702,6 +714,8 @@ void ui_displayPoolMarginScreen( ); } +#ifdef APP_FEATURE_POOL_REGISTRATION + void ui_displayPoolOwnerScreen( const pool_owner_t* owner, uint32_t ownerIndex, @@ -859,6 +873,8 @@ void ui_displayIpPortScreen( ); } +#endif // APP_FEATURE_POOL_REGISTRATION + void ui_displayInputScreen( const sign_tx_transaction_input_t* input, ui_callback_fn_t callback) diff --git a/src/uiScreens_bagl.h b/src/uiScreens_bagl.h index f4073130..abb162bb 100644 --- a/src/uiScreens_bagl.h +++ b/src/uiScreens_bagl.h @@ -134,6 +134,8 @@ void ui_displayPoolMarginScreen( ui_callback_fn_t callback ); +#ifdef APP_FEATURE_POOL_REGISTRATION + __noinline_due_to_stack__ void ui_displayPoolOwnerScreen( const pool_owner_t* owner, @@ -167,6 +169,8 @@ void ui_displayIpPortScreen( ui_callback_fn_t callback ); +#endif // APP_FEATURE_POOL_REGISTRATION + __noinline_due_to_stack__ void ui_displayInputScreen( const sign_tx_transaction_input_t* input, diff --git a/src/uiScreens_nbgl.c b/src/uiScreens_nbgl.c index db1b7bf9..1dfca96a 100644 --- a/src/uiScreens_nbgl.c +++ b/src/uiScreens_nbgl.c @@ -620,6 +620,8 @@ void ui_getPoolMarginScreen( TRACE("%s", line1); } +#ifdef APP_FEATURE_POOL_REGISTRATION + void ui_getPoolOwnerScreen( char* firstLine, const size_t firstLineSize, @@ -748,6 +750,8 @@ void ui_getIpPortScreen( ASSERT(strlen(portStr) + 1 < portStrSize); } +#endif // APP_FEATURE_POOL_REGISTRATION + void ui_getInputScreen( char* line, const size_t lineSize, diff --git a/src/uiScreens_nbgl.h b/src/uiScreens_nbgl.h index b7424145..e5120cfa 100644 --- a/src/uiScreens_nbgl.h +++ b/src/uiScreens_nbgl.h @@ -165,6 +165,8 @@ void ui_getPoolMarginScreen( uint64_t marginNumerator, uint64_t marginDenominator ); +#ifdef APP_FEATURE_POOL_REGISTRATION + __noinline_due_to_stack__ void ui_getPoolOwnerScreen( char* firstLine, @@ -200,6 +202,8 @@ void ui_getIpPortScreen( const ipport_t* port ); +#endif // APP_FEATURE_POOL_REGISTRATION + __noinline_due_to_stack__ void ui_getInputScreen( char* line,