mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-25 14:50:57 +00:00
legacy: Support multiple change-outputs.
This commit is contained in:
parent
eb28998f98
commit
24bf352577
@ -18,7 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "bignum.h"
|
#include "bignum.h"
|
||||||
@ -440,6 +442,14 @@ void layoutFeeOverThreshold(const CoinInfo *coin, uint64_t fee) {
|
|||||||
_("Send anyway?"), NULL);
|
_("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) {
|
void layoutSignMessage(const uint8_t *msg, uint32_t len) {
|
||||||
const char **str = NULL;
|
const char **str = NULL;
|
||||||
if (!is_valid_ascii(msg, len)) {
|
if (!is_valid_ascii(msg, len)) {
|
||||||
|
@ -52,6 +52,7 @@ void layoutConfirmOpReturn(const uint8_t *data, uint32_t size);
|
|||||||
void layoutConfirmTx(const CoinInfo *coin, uint64_t amount_out,
|
void layoutConfirmTx(const CoinInfo *coin, uint64_t amount_out,
|
||||||
uint64_t amount_fee);
|
uint64_t amount_fee);
|
||||||
void layoutFeeOverThreshold(const CoinInfo *coin, uint64_t 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 layoutSignMessage(const uint8_t *msg, uint32_t len);
|
||||||
void layoutVerifyAddress(const CoinInfo *coin, const char *address);
|
void layoutVerifyAddress(const CoinInfo *coin, const char *address);
|
||||||
void layoutVerifyMessage(const uint8_t *msg, uint32_t len);
|
void layoutVerifyMessage(const uint8_t *msg, uint32_t len);
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
static uint32_t inputs_count;
|
static uint32_t inputs_count;
|
||||||
static uint32_t outputs_count;
|
static uint32_t outputs_count;
|
||||||
|
static uint32_t change_count;
|
||||||
static const CoinInfo *coin;
|
static const CoinInfo *coin;
|
||||||
static CONFIDENTIAL HDNode root;
|
static CONFIDENTIAL HDNode root;
|
||||||
static CONFIDENTIAL HDNode node;
|
static CONFIDENTIAL HDNode node;
|
||||||
@ -103,6 +104,9 @@ static uint32_t tx_weight;
|
|||||||
/* transaction segwit overhead 2 marker */
|
/* transaction segwit overhead 2 marker */
|
||||||
#define TXSIZE_SEGWIT_OVERHEAD 2
|
#define TXSIZE_SEGWIT_OVERHEAD 2
|
||||||
|
|
||||||
|
/* The maximum number of change-outputs allowed without user confirmation. */
|
||||||
|
#define MAX_SILENT_CHANGE_COUNT 2
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SIGHASH_ALL = 1,
|
SIGHASH_ALL = 1,
|
||||||
SIGHASH_FORKID = 0x40,
|
SIGHASH_FORKID = 0x40,
|
||||||
@ -551,6 +555,7 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin,
|
|||||||
to_spend = 0;
|
to_spend = 0;
|
||||||
spending = 0;
|
spending = 0;
|
||||||
change_spend = 0;
|
change_spend = 0;
|
||||||
|
change_count = 0;
|
||||||
memzero(&input, sizeof(TxInputType));
|
memzero(&input, sizeof(TxInputType));
|
||||||
memzero(&resp, sizeof(TxRequest));
|
memzero(&resp, sizeof(TxRequest));
|
||||||
|
|
||||||
@ -840,11 +845,18 @@ static bool signing_check_output(TxOutputType *txoutput) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_change) {
|
if (is_change) {
|
||||||
if (change_spend == 0) { // not set
|
if (change_spend + txoutput->amount < change_spend) {
|
||||||
change_spend = txoutput->amount;
|
fsm_sendFailure(FailureType_Failure_DataError, _("Value overflow"));
|
||||||
} else {
|
signing_abort();
|
||||||
/* We only skip confirmation for the first change output */
|
return false;
|
||||||
is_change = 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool signing_check_fee(void) {
|
static bool signing_confirm_tx(void) {
|
||||||
if (coin->negative_fee) {
|
if (coin->negative_fee) {
|
||||||
// bypass check for negative fee coins, required for reward TX
|
// bypass check for negative fee coins, required for reward TX
|
||||||
} else {
|
} else {
|
||||||
@ -912,6 +924,16 @@ static bool signing_check_fee(void) {
|
|||||||
} else {
|
} else {
|
||||||
fee = 0;
|
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
|
// last confirmation
|
||||||
layoutConfirmTx(coin, to_spend - change_spend, fee);
|
layoutConfirmTx(coin, to_spend - change_spend, fee);
|
||||||
if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) {
|
if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) {
|
||||||
@ -944,7 +966,7 @@ static void phase1_request_next_output(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
hasher_Final(&hasher_outputs, hash_outputs);
|
hasher_Final(&hasher_outputs, hash_outputs);
|
||||||
if (!signing_check_fee()) {
|
if (!signing_confirm_tx()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Everything was checked, now phase 2 begins and the transaction is signed.
|
// Everything was checked, now phase 2 begins and the transaction is signed.
|
||||||
|
Loading…
Reference in New Issue
Block a user