Skip to content

Commit 7ae2d77

Browse files
Using swap infrastructure from the SDK
1 parent 09faf3d commit 7ae2d77

File tree

8 files changed

+55
-52
lines changed

8 files changed

+55
-52
lines changed

src/boilerplate/dispatcher.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
/* SDK headers */
44
#include "buffer.h"
55
#include "os.h"
6+
#include "swap_error_code_helpers.h"
67

78
/* Local headers */
89
#include "parser.h"
10+
#include "sw.h"
911

1012
// Forward declaration
1113
struct dispatcher_context_s;
@@ -49,6 +51,12 @@ static inline void SEND_RESPONSE(struct dispatcher_context_s *dc,
4951
}
5052

5153
static inline void SEND_SW_EC(struct dispatcher_context_s *dc, uint16_t sw, uint16_t error_code) {
54+
if (sw == SW_FAIL_SWAP) {
55+
send_swap_error_simple(SW_FAIL_SWAP, (error_code >> 8) & 0xFF, (error_code & 0xFF));
56+
// unreachable
57+
os_sched_exit(0);
58+
}
59+
5260
uint8_t error_code_buf[2];
5361
error_code_buf[0] = (error_code >> 8) & 0xFF;
5462
error_code_buf[1] = error_code & 0xFF;

src/error_codes.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#pragma once
22

3+
/* SDK headers */
4+
#include "swap_error_code_helpers.h"
5+
36
/**
47
* REGISTER_WALLET
58
*/
@@ -68,46 +71,88 @@
6871

6972
// Internal application error, forward to the firmware team for analysis.
7073
#define EC_SWAP_ERROR_INTERNAL 0x0000
74+
_Static_assert((EC_SWAP_ERROR_INTERNAL >> 8) == SWAP_EC_ERROR_INTERNAL,
75+
"SWAP error code value does not match the SDK one");
7176

7277
// The amount does not match the one validated in Exchange.
7378
#define EC_SWAP_ERROR_WRONG_AMOUNT 0x0100
79+
_Static_assert((EC_SWAP_ERROR_WRONG_AMOUNT >> 8) == SWAP_EC_ERROR_WRONG_AMOUNT,
80+
"SWAP error code value does not match the SDK one");
7481

7582
// The destination address does not match the one validated in Exchange.
7683
#define EC_SWAP_ERROR_WRONG_DESTINATION 0x0200
84+
_Static_assert((EC_SWAP_ERROR_WRONG_DESTINATION >> 8) == SWAP_EC_ERROR_WRONG_DESTINATION,
85+
"SWAP error code value does not match the SDK one");
7786

7887
// The fees are different from what was validated in Exchange.
7988
#define EC_SWAP_ERROR_WRONG_FEES 0x0300
89+
_Static_assert((EC_SWAP_ERROR_WRONG_FEES >> 8) == SWAP_EC_ERROR_WRONG_FEES,
90+
"SWAP error code value does not match the SDK one");
8091

8192
// The method used is invalid in Exchange context.
8293
#define EC_SWAP_ERROR_WRONG_METHOD 0x0400
94+
_Static_assert((EC_SWAP_ERROR_WRONG_METHOD >> 8) == SWAP_EC_ERROR_WRONG_METHOD,
95+
"SWAP error code value does not match the SDK one");
8396
// Only default wallet policies can be used in swaps.
8497
#define EC_SWAP_ERROR_WRONG_METHOD_NONDEFAULT_POLICY 0x0401
98+
_Static_assert((EC_SWAP_ERROR_WRONG_METHOD_NONDEFAULT_POLICY >> 8) == SWAP_EC_ERROR_WRONG_METHOD,
99+
"SWAP error code value does not match the SDK one");
85100
// No external inputs allowed in swap transactions.
86101
#define EC_SWAP_ERROR_WRONG_METHOD_EXTERNAL_INPUTS 0x0402
102+
_Static_assert((EC_SWAP_ERROR_WRONG_METHOD_EXTERNAL_INPUTS >> 8) == SWAP_EC_ERROR_WRONG_METHOD,
103+
"SWAP error code value does not match the SDK one");
87104
// Segwit transaction in swap must have the non-witness UTXO in the PSBT.
88105
#define EC_SWAP_ERROR_WRONG_METHOD_MISSING_NONWITNESSUTXO 0x0403
106+
_Static_assert((EC_SWAP_ERROR_WRONG_METHOD_MISSING_NONWITNESSUTXO >> 8) ==
107+
SWAP_EC_ERROR_WRONG_METHOD,
108+
"SWAP error code value does not match the SDK one");
89109
// Standard swap transaction must have exactly 1 external output.
90110
#define EC_SWAP_ERROR_WRONG_METHOD_WRONG_N_OF_OUTPUTS 0x0404
111+
_Static_assert((EC_SWAP_ERROR_WRONG_METHOD_WRONG_N_OF_OUTPUTS >> 8) == SWAP_EC_ERROR_WRONG_METHOD,
112+
"SWAP error code value does not match the SDK one");
91113
// Invalid or unsupported script for external output.
92114
#define EC_SWAP_ERROR_WRONG_METHOD_WRONG_UNSUPPORTED_OUTPUT 0x0405
115+
_Static_assert((EC_SWAP_ERROR_WRONG_METHOD_WRONG_UNSUPPORTED_OUTPUT >> 8) ==
116+
SWAP_EC_ERROR_WRONG_METHOD,
117+
"SWAP error code value does not match the SDK one");
93118

94119
// The mode used for the cross-chain hash validation is not supported.
95120
#define EC_SWAP_ERROR_CROSSCHAIN_WRONG_MODE 0x0500
121+
_Static_assert((EC_SWAP_ERROR_CROSSCHAIN_WRONG_MODE >> 8) == SWAP_EC_ERROR_CROSSCHAIN_WRONG_MODE,
122+
"SWAP error code value does not match the SDK one");
96123

97124
// The method used is invalid in cross-chain Exchange context.
98125
#define EC_SWAP_ERROR_CROSSCHAIN_WRONG_METHOD 0x0600
126+
_Static_assert((EC_SWAP_ERROR_CROSSCHAIN_WRONG_METHOD >> 8) ==
127+
SWAP_EC_ERROR_CROSSCHAIN_WRONG_METHOD,
128+
"SWAP error code value does not match the SDK one");
99129
// The first output must be OP_RETURN <data> for a cross-chain swap.
100130
#define EC_SWAP_ERROR_CROSSCHAIN_WRONG_METHOD_INVALID_FIRST_OUTPUT 0x0601
131+
_Static_assert((EC_SWAP_ERROR_CROSSCHAIN_WRONG_METHOD_INVALID_FIRST_OUTPUT >> 8) ==
132+
SWAP_EC_ERROR_CROSSCHAIN_WRONG_METHOD,
133+
"SWAP error code value does not match the SDK one");
101134
// OP_RETURN with non-zero value is not supported.
102135
#define EC_SWAP_ERROR_CROSSCHAIN_WRONG_METHOD_NONZERO_AMOUNT 0x0602
136+
_Static_assert((EC_SWAP_ERROR_CROSSCHAIN_WRONG_METHOD_NONZERO_AMOUNT >> 8) ==
137+
SWAP_EC_ERROR_CROSSCHAIN_WRONG_METHOD,
138+
"SWAP error code value does not match the SDK one");
103139

104140
// The hash for the cross-chain transaction does not match the validated value.
105141
#define EC_SWAP_ERROR_CROSSCHAIN_WRONG_HASH 0x0700
142+
_Static_assert((EC_SWAP_ERROR_CROSSCHAIN_WRONG_HASH >> 8) == SWAP_EC_ERROR_CROSSCHAIN_WRONG_HASH,
143+
"SWAP error code value does not match the SDK one");
106144

107145
// A generic or unspecified error not covered by the specific error codes above. Refer to the
108146
// remaining bytes for further details on the error.
109147
#define EC_SWAP_ERROR_GENERIC 0xFF00
148+
_Static_assert((EC_SWAP_ERROR_GENERIC >> 8) == SWAP_EC_ERROR_GENERIC,
149+
"SWAP error code value does not match the SDK one");
110150
// Unknown swap mode.
111151
#define EC_SWAP_ERROR_GENERIC_UNKNOWN_MODE 0xFF01
152+
_Static_assert((EC_SWAP_ERROR_GENERIC_UNKNOWN_MODE >> 8) == SWAP_EC_ERROR_GENERIC,
153+
"SWAP error code value does not match the SDK one");
112154
// handle_swap_sign_transaction.c::copy_transaction_parameters failed.
113155
#define EC_SWAP_ERROR_GENERIC_COPY_TRANSACTION_PARAMETERS_FAILED 0xFF02
156+
_Static_assert((EC_SWAP_ERROR_GENERIC_COPY_TRANSACTION_PARAMETERS_FAILED >> 8) ==
157+
SWAP_EC_ERROR_GENERIC,
158+
"SWAP error code value does not match the SDK one");

src/handler/get_wallet_address.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
#include "error_codes.h"
3434
#include "get_merkle_leaf_element.h"
3535
#include "get_preimage.h"
36-
#include "handle_swap_sign_transaction.h"
3736
#include "handlers.h"
3837
#include "io_ext.h"
3938
#include "menu.h"
@@ -159,7 +158,6 @@ void handler_get_wallet_address(dispatcher_context_t *dc, uint8_t protocol_versi
159158
if (G_called_from_swap && !is_wallet_default) {
160159
PRINTF("Must be a default wallet policy for swap feature\n");
161160
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_WRONG_METHOD_NONDEFAULT_POLICY);
162-
finalize_exchange_sign_transaction(false);
163161
}
164162

165163
{

src/handler/sign_psbt.c

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
#include "get_merkleized_map.h"
4545
#include "get_merkleized_map_value.h"
4646
#include "get_preimage.h"
47-
#include "handle_swap_sign_transaction.h"
4847
#include "handlers.h"
4948
#include "menu.h"
5049
#include "merkle.h"
@@ -1029,22 +1028,19 @@ execute_swap_checks(dispatcher_context_t *dc, sign_psbt_state_t *st) {
10291028
if (!st->is_wallet_default) {
10301029
PRINTF("Must be a default wallet policy for swap feature\n");
10311030
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_WRONG_METHOD_NONDEFAULT_POLICY);
1032-
finalize_exchange_sign_transaction(false);
10331031
}
10341032

10351033
// No external inputs allowed
10361034
if (st->n_external_inputs > 0) {
10371035
PRINTF("External inputs not allowed in swap transactions\n");
10381036
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_WRONG_METHOD_EXTERNAL_INPUTS);
1039-
finalize_exchange_sign_transaction(false);
10401037
}
10411038

10421039
if (st->warnings.missing_nonwitnessutxo || st->warnings.non_default_sighash) {
10431040
// Do not allow transactions with missing non-witness utxos or non-default sighash flags
10441041
PRINTF(
10451042
"Missing non-witness utxo or non-default sighash flags are not allowed during swaps\n");
10461043
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_WRONG_METHOD_MISSING_NONWITNESSUTXO);
1047-
finalize_exchange_sign_transaction(false);
10481044
}
10491045

10501046
uint64_t fee = st->inputs_total_amount - st->outputs.total_amount;
@@ -1060,7 +1056,6 @@ execute_swap_checks(dispatcher_context_t *dc, sign_psbt_state_t *st) {
10601056
if (st->n_external_outputs != 1) {
10611057
PRINTF("Standard swap transaction must have exactly 1 external output\n");
10621058
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_WRONG_METHOD_WRONG_N_OF_OUTPUTS);
1063-
finalize_exchange_sign_transaction(false);
10641059
}
10651060
} else if (G_swap_state.mode == SWAP_MODE_CROSSCHAIN) {
10661061
// There must be exactly 2 external outputs; the first is the OP_RETURN
@@ -1070,7 +1065,6 @@ execute_swap_checks(dispatcher_context_t *dc, sign_psbt_state_t *st) {
10701065
if (st->n_external_outputs != 2) {
10711066
PRINTF("Cross-chain swap transaction must have exactly 2 external outputs\n");
10721067
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_WRONG_METHOD_WRONG_N_OF_OUTPUTS);
1073-
finalize_exchange_sign_transaction(false);
10741068
}
10751069

10761070
uint8_t *opreturn_script = st->outputs.output_scripts[0];
@@ -1081,12 +1075,11 @@ execute_swap_checks(dispatcher_context_t *dc, sign_psbt_state_t *st) {
10811075
SEND_SW_EC(dc,
10821076
SW_FAIL_SWAP,
10831077
EC_SWAP_ERROR_CROSSCHAIN_WRONG_METHOD_INVALID_FIRST_OUTPUT);
1084-
finalize_exchange_sign_transaction(false);
10851078
}
10861079

10871080
uint8_t second_byte = opreturn_script[1];
1088-
size_t push_opcode_size; // the length of the push opcode (1 or 2 bytes)
1089-
size_t data_size; // the length of the actual data embedded in the OP_RETURN output
1081+
size_t push_opcode_size = 0; // the length of the push opcode (1 or 2 bytes)
1082+
size_t data_size = 0; // the length of the actual data embedded in the OP_RETURN output
10901083
if (2 <= second_byte && second_byte <= 75) {
10911084
push_opcode_size = 1;
10921085
data_size = second_byte;
@@ -1100,21 +1093,18 @@ execute_swap_checks(dispatcher_context_t *dc, sign_psbt_state_t *st) {
11001093
// so we don't bother parsing.
11011094
PRINTF("Unsupported or invalid OP_RETURN Script in cross-chain swap\n");
11021095
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_CROSSCHAIN_WRONG_METHOD);
1103-
finalize_exchange_sign_transaction(false);
11041096
}
11051097

11061098
// Make sure there is a singla data push
11071099
if (opreturn_script_len != 1 + push_opcode_size + data_size) {
11081100
PRINTF("Invalid OP_RETURN Script length in cross-chain swap\n");
11091101
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_CROSSCHAIN_WRONG_METHOD);
1110-
finalize_exchange_sign_transaction(false);
11111102
}
11121103

11131104
// Make sure the output's value is 0
11141105
if (opreturn_amount != 0) {
11151106
PRINTF("OP_RETURN with non-zero value during cross-chain swap\n");
11161107
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_CROSSCHAIN_WRONG_METHOD_NONZERO_AMOUNT);
1117-
finalize_exchange_sign_transaction(false);
11181108
}
11191109

11201110
// verify the hash in the data payload is the expected one
@@ -1125,18 +1115,15 @@ execute_swap_checks(dispatcher_context_t *dc, sign_psbt_state_t *st) {
11251115
sizeof(expected_payin_hash)) != 0) {
11261116
PRINTF("Mismatching payin hash in cross-chain swap\n");
11271117
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_CROSSCHAIN_WRONG_HASH);
1128-
finalize_exchange_sign_transaction(false);
11291118
}
11301119
} else if (G_swap_state.mode == SWAP_MODE_ERROR) {
11311120
// an error was detected in handle_swap_sign_transaction.c::copy_transaction_parameters
11321121
// special case only to improve error reporting in debug mode
11331122
PRINTF("Invalid parameters for swap feature\n");
11341123
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_GENERIC_COPY_TRANSACTION_PARAMETERS_FAILED);
1135-
finalize_exchange_sign_transaction(false);
11361124
} else {
11371125
PRINTF("Unknown swap mode: %d\n", G_swap_state.mode);
11381126
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_GENERIC_UNKNOWN_MODE);
1139-
finalize_exchange_sign_transaction(false);
11401127
}
11411128

11421129
LEDGER_ASSERT(0 <= swap_dest_idx && swap_dest_idx < N_CACHED_EXTERNAL_OUTPUTS,
@@ -1146,14 +1133,12 @@ execute_swap_checks(dispatcher_context_t *dc, sign_psbt_state_t *st) {
11461133
if (fee != G_swap_state.fees) {
11471134
PRINTF("Mismatching fee for swap\n");
11481135
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_WRONG_FEES);
1149-
finalize_exchange_sign_transaction(false);
11501136
}
11511137

11521138
uint64_t spent_amount = st->outputs.total_amount - st->outputs.change_total_amount;
11531139
if (spent_amount != G_swap_state.amount) {
11541140
PRINTF("Mismatching spent amount for swap\n");
11551141
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_WRONG_AMOUNT);
1156-
finalize_exchange_sign_transaction(false);
11571142
}
11581143

11591144
// Compute this output's address
@@ -1164,7 +1149,6 @@ execute_swap_checks(dispatcher_context_t *dc, sign_psbt_state_t *st) {
11641149
output_description)) {
11651150
PRINTF("Invalid or unsupported script for external output\n");
11661151
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_WRONG_METHOD_WRONG_UNSUPPORTED_OUTPUT);
1167-
finalize_exchange_sign_transaction(false);
11681152
}
11691153

11701154
char output_description_len = strlen(output_description);
@@ -1187,7 +1171,6 @@ execute_swap_checks(dispatcher_context_t *dc, sign_psbt_state_t *st) {
11871171
}
11881172
PRINTF("\n");
11891173
SEND_SW_EC(dc, SW_FAIL_SWAP, EC_SWAP_ERROR_WRONG_DESTINATION);
1190-
finalize_exchange_sign_transaction(false);
11911174
}
11921175

11931176
return true;
@@ -2204,11 +2187,6 @@ void handler_sign_psbt(dispatcher_context_t *dc, uint8_t protocol_version) {
22042187
if (!sign_result) {
22052188
return;
22062189
}
2207-
2208-
// Only if called from swap, the app should terminate after sending the response
2209-
if (G_called_from_swap) {
2210-
G_swap_state.should_exit = true;
2211-
}
22122190
}
22132191

22142192
// MuSig2: if there is an active session at the end of round 1, we move it to persistent

src/main.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
#include "constants.h"
3232
#include "debug.h"
3333
#include "dispatcher.h"
34-
#include "handle_swap_sign_transaction.h"
3534
#include "handlers.h"
3635
#include "io_ext.h"
3736
#include "menu.h"
@@ -86,12 +85,6 @@ const command_descriptor_t COMMAND_DESCRIPTORS[] = {
8685

8786
static void initialize_app_globals() {
8887
ioe_reset_timeouts();
89-
90-
// We only zero out should_exit field and not the entire G_swap_state, as
91-
// we need the globals initialization to happen _after_ calling copy_transaction_parameters when
92-
// processing a SIGN_TRANSACTION request from the swap app (which initializes the other fields
93-
// of G_swap_state).
94-
G_swap_state.should_exit = false;
9588
}
9689

9790
/**
@@ -168,9 +161,5 @@ void app_main() {
168161
sizeof(COMMAND_DESCRIPTORS) / sizeof(COMMAND_DESCRIPTORS[0]),
169162
ui_menu_main,
170163
&cmd);
171-
if (G_called_from_swap && G_swap_state.should_exit) {
172-
// Bitcoin app will keep listening as long as it does not receive a valid TX
173-
finalize_exchange_sign_transaction(true);
174-
}
175164
}
176165
}

src/swap/handle_swap_sign_transaction.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#include <assert.h>
22

3-
#include "handle_swap_sign_transaction.h"
4-
53
/* SDK headers */
64
#include "os.h"
75
#include "read.h"
@@ -13,9 +11,6 @@
1311
#include "swap_globals.h"
1412
#include "usbd_core.h"
1513

16-
// Save the BSS address where we will write the return value when finished
17-
static uint8_t* G_swap_sign_return_value_address;
18-
1914
bool swap_copy_transaction_parameters(create_transaction_parameters_t* sign_transaction_params) {
2015
char destination_address[65];
2116
uint8_t destination_address_extra_data[33];
@@ -56,7 +51,6 @@ bool swap_copy_transaction_parameters(create_transaction_parameters_t* sign_tran
5651
sign_transaction_params->fee_amount_length);
5752

5853
os_explicit_zero_BSS_segment();
59-
G_swap_sign_return_value_address = &sign_transaction_params->result;
6054

6155
G_swap_state.amount = read_u64_be(amount, 0);
6256
G_swap_state.fees = read_u64_be(fees, 0);
@@ -89,8 +83,3 @@ bool swap_copy_transaction_parameters(create_transaction_parameters_t* sign_tran
8983

9084
return true;
9185
}
92-
93-
void __attribute__((noreturn)) finalize_exchange_sign_transaction(bool is_success) {
94-
*G_swap_sign_return_value_address = is_success;
95-
os_lib_end();
96-
}

src/swap/handle_swap_sign_transaction.h

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/swap/swap_globals.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ typedef struct swap_globals_s {
1212
uint64_t amount;
1313
uint64_t fees;
1414
char destination_address[65];
15-
unsigned char should_exit;
1615
unsigned char mode;
1716
uint8_t payin_extra_id[1 + 32];
1817
} swap_globals_t;

0 commit comments

Comments
 (0)