1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-10 23:40:58 +00:00

legacy: Support multiple change-outputs.

This commit is contained in:
Andrew Kozlik 2020-07-08 18:43:03 +02:00 committed by Andrew Kozlik
parent eb28998f98
commit 24bf352577
3 changed files with 40 additions and 7 deletions

View File

@ -18,7 +18,9 @@
*/
#include <ctype.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "bignum.h"
@ -440,6 +442,14 @@ void layoutFeeOverThreshold(const CoinInfo *coin, uint64_t fee) {
_("Send anyway?"), NULL);
}
void layoutChangeCountOverThreshold(uint32_t change_count) {
char str_change[21] = {0};
snprintf(str_change, sizeof(str_change), "There are %" PRIu32, change_count);
layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), NULL,
_("Warning!"), str_change, _("change-outputs."), NULL,
_("Continue?"), NULL);
}
void layoutSignMessage(const uint8_t *msg, uint32_t len) {
const char **str = NULL;
if (!is_valid_ascii(msg, len)) {

View File

@ -52,6 +52,7 @@ void layoutConfirmOpReturn(const uint8_t *data, uint32_t size);
void layoutConfirmTx(const CoinInfo *coin, uint64_t amount_out,
uint64_t amount_fee);
void layoutFeeOverThreshold(const CoinInfo *coin, uint64_t fee);
void layoutChangeCountOverThreshold(uint32_t change_count);
void layoutSignMessage(const uint8_t *msg, uint32_t len);
void layoutVerifyAddress(const CoinInfo *coin, const char *address);
void layoutVerifyMessage(const uint8_t *msg, uint32_t len);

View File

@ -32,6 +32,7 @@
static uint32_t inputs_count;
static uint32_t outputs_count;
static uint32_t change_count;
static const CoinInfo *coin;
static CONFIDENTIAL HDNode root;
static CONFIDENTIAL HDNode node;
@ -103,6 +104,9 @@ static uint32_t tx_weight;
/* transaction segwit overhead 2 marker */
#define TXSIZE_SEGWIT_OVERHEAD 2
/* The maximum number of change-outputs allowed without user confirmation. */
#define MAX_SILENT_CHANGE_COUNT 2
enum {
SIGHASH_ALL = 1,
SIGHASH_FORKID = 0x40,
@ -551,6 +555,7 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin,
to_spend = 0;
spending = 0;
change_spend = 0;
change_count = 0;
memzero(&input, sizeof(TxInputType));
memzero(&resp, sizeof(TxRequest));
@ -840,11 +845,18 @@ static bool signing_check_output(TxOutputType *txoutput) {
}
if (is_change) {
if (change_spend == 0) { // not set
change_spend = txoutput->amount;
} else {
/* We only skip confirmation for the first change output */
is_change = false;
if (change_spend + txoutput->amount < change_spend) {
fsm_sendFailure(FailureType_Failure_DataError, _("Value overflow"));
signing_abort();
return false;
}
change_spend += txoutput->amount;
change_count++;
if (change_count <= 0) {
fsm_sendFailure(FailureType_Failure_DataError, _("Value overflow"));
signing_abort();
return false;
}
}
@ -885,7 +897,7 @@ static bool signing_check_output(TxOutputType *txoutput) {
return true;
}
static bool signing_check_fee(void) {
static bool signing_confirm_tx(void) {
if (coin->negative_fee) {
// bypass check for negative fee coins, required for reward TX
} else {
@ -912,6 +924,16 @@ static bool signing_check_fee(void) {
} else {
fee = 0;
}
if (change_count > MAX_SILENT_CHANGE_COUNT) {
layoutChangeCountOverThreshold(change_count);
if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) {
fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
signing_abort();
return false;
}
}
// last confirmation
layoutConfirmTx(coin, to_spend - change_spend, fee);
if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) {
@ -944,7 +966,7 @@ static void phase1_request_next_output(void) {
}
#endif
hasher_Final(&hasher_outputs, hash_outputs);
if (!signing_check_fee()) {
if (!signing_confirm_tx()) {
return;
}
// Everything was checked, now phase 2 begins and the transaction is signed.