mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-27 07:40:59 +00:00
feat(legacy): implement amount_unit for SignTx
This commit is contained in:
parent
7f0e939359
commit
1d3166017d
@ -26,7 +26,7 @@ const CoinInfo coins[COINS_COUNT] = {
|
||||
% for c in supported_on("trezor1", bitcoin):
|
||||
{
|
||||
.coin_name = ${c_str(c.coin_name)},
|
||||
.coin_shortcut = ${c_str(" " + c.coin_shortcut)},
|
||||
.coin_shortcut = ${c_str(c.coin_shortcut)},
|
||||
.maxfee_kb = ${c_int(c.maxfee_kb)},
|
||||
.signed_message_header = ${signed_message_header(c.signed_message_header)},
|
||||
.has_segwit = ${c_bool(c.segwit)},
|
||||
|
@ -92,18 +92,18 @@ static const char *address_n_str(const uint32_t *address_n,
|
||||
const char *abbr = 0;
|
||||
if (native_segwit) {
|
||||
if (coin && coin->has_segwit && coin->bech32_prefix) {
|
||||
abbr = coin->coin_shortcut + 1;
|
||||
abbr = coin->coin_shortcut;
|
||||
}
|
||||
} else if (p2sh_segwit) {
|
||||
if (coin && coin->has_segwit) {
|
||||
abbr = coin->coin_shortcut + 1;
|
||||
abbr = coin->coin_shortcut;
|
||||
}
|
||||
} else {
|
||||
if (coin) {
|
||||
if (coin->has_segwit) {
|
||||
legacy = true;
|
||||
}
|
||||
abbr = coin->coin_shortcut + 1;
|
||||
abbr = coin->coin_shortcut;
|
||||
#if !BITCOIN_ONLY
|
||||
} else {
|
||||
abbr = slip44_extras(address_n[1]);
|
||||
@ -346,10 +346,51 @@ static void render_address_dialog(const CoinInfo *coin, const char *address,
|
||||
oledRefresh();
|
||||
}
|
||||
|
||||
void layoutConfirmOutput(const CoinInfo *coin, const TxOutputType *out) {
|
||||
static size_t format_coin_amount(uint64_t amount, const char *prefix,
|
||||
const CoinInfo *coin, AmountUnit amount_unit,
|
||||
char *output, size_t output_len) {
|
||||
// " " + (optional "m"/u") + shortcut + ending zero -> 16 should suffice
|
||||
char suffix[16];
|
||||
memzero(suffix, sizeof(suffix));
|
||||
suffix[0] = ' ';
|
||||
uint32_t decimals = coin->decimals;
|
||||
switch (amount_unit) {
|
||||
case AmountUnit_SATOSHI:
|
||||
decimals = 0;
|
||||
strlcpy(suffix + 1, "sat ", sizeof(suffix) - 1);
|
||||
strlcpy(suffix + 5, coin->coin_shortcut, sizeof(suffix) - 5);
|
||||
break;
|
||||
case AmountUnit_MILLIBITCOIN:
|
||||
if (decimals >= 6) {
|
||||
decimals -= 6;
|
||||
suffix[1] = 'u';
|
||||
strlcpy(suffix + 2, coin->coin_shortcut, sizeof(suffix) - 2);
|
||||
} else {
|
||||
strlcpy(suffix + 1, coin->coin_shortcut, sizeof(suffix) - 1);
|
||||
}
|
||||
break;
|
||||
case AmountUnit_MICROBITCOIN:
|
||||
if (decimals >= 3) {
|
||||
decimals -= 3;
|
||||
suffix[1] = 'm';
|
||||
strlcpy(suffix + 2, coin->coin_shortcut, sizeof(suffix) - 2);
|
||||
} else {
|
||||
strlcpy(suffix + 1, coin->coin_shortcut, sizeof(suffix) - 1);
|
||||
}
|
||||
break;
|
||||
default: // AmountUnit_BITCOIN
|
||||
strlcpy(suffix + 1, coin->coin_shortcut, sizeof(suffix) - 1);
|
||||
break;
|
||||
}
|
||||
return bn_format_uint64(amount, prefix, suffix, decimals, 0, false, output,
|
||||
output_len);
|
||||
}
|
||||
|
||||
void layoutConfirmOutput(const CoinInfo *coin, AmountUnit amount_unit,
|
||||
const TxOutputType *out) {
|
||||
char str_out[32 + 3] = {0};
|
||||
bn_format_uint64(out->amount, NULL, coin->coin_shortcut, coin->decimals, 0,
|
||||
false, str_out, sizeof(str_out) - 3);
|
||||
format_coin_amount(out->amount, NULL, coin, amount_unit, str_out,
|
||||
sizeof(str_out) - 3);
|
||||
strlcat(str_out, " to", sizeof(str_out));
|
||||
const char *address = out->address;
|
||||
const char *extra_line =
|
||||
@ -423,9 +464,9 @@ void layoutConfirmOpReturn(const uint8_t *data, uint32_t size) {
|
||||
NULL);
|
||||
}
|
||||
|
||||
static bool formatAmountDifference(const CoinInfo *coin, uint64_t amount1,
|
||||
uint64_t amount2, char *output,
|
||||
size_t output_length) {
|
||||
static bool formatAmountDifference(const CoinInfo *coin, AmountUnit amount_unit,
|
||||
uint64_t amount1, uint64_t amount2,
|
||||
char *output, size_t output_length) {
|
||||
uint64_t abs_diff = 0;
|
||||
const char *sign = NULL;
|
||||
if (amount1 >= amount2) {
|
||||
@ -435,17 +476,20 @@ static bool formatAmountDifference(const CoinInfo *coin, uint64_t amount1,
|
||||
sign = "-";
|
||||
}
|
||||
|
||||
return bn_format_uint64(abs_diff, sign, coin->coin_shortcut, coin->decimals,
|
||||
0, false, output, output_length) != 0;
|
||||
return format_coin_amount(abs_diff, sign, coin, amount_unit, output,
|
||||
output_length) != 0;
|
||||
}
|
||||
|
||||
void layoutConfirmTx(const CoinInfo *coin, uint64_t total_in,
|
||||
uint64_t total_out, uint64_t change_out) {
|
||||
void layoutConfirmTx(const CoinInfo *coin, AmountUnit amount_unit,
|
||||
uint64_t total_in, uint64_t total_out,
|
||||
uint64_t change_out) {
|
||||
char str_out[32] = {0};
|
||||
formatAmountDifference(coin, total_in, change_out, str_out, sizeof(str_out));
|
||||
formatAmountDifference(coin, amount_unit, total_in, change_out, str_out,
|
||||
sizeof(str_out));
|
||||
|
||||
char str_fee[32] = {0};
|
||||
formatAmountDifference(coin, total_in, total_out, str_fee, sizeof(str_fee));
|
||||
formatAmountDifference(coin, amount_unit, total_in, total_out, str_fee,
|
||||
sizeof(str_fee));
|
||||
|
||||
layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), NULL,
|
||||
_("Really send"), str_out, _("from your wallet?"),
|
||||
@ -458,8 +502,8 @@ void layoutConfirmReplacement(const char *description, uint8_t txid[32]) {
|
||||
description, str[0], str[1], str[2], str[3], NULL);
|
||||
}
|
||||
|
||||
void layoutConfirmModifyFee(const CoinInfo *coin, uint64_t fee_old,
|
||||
uint64_t fee_new) {
|
||||
void layoutConfirmModifyFee(const CoinInfo *coin, AmountUnit amount_unit,
|
||||
uint64_t fee_old, uint64_t fee_new) {
|
||||
char str_fee_change[32] = {0};
|
||||
char str_fee_new[32] = {0};
|
||||
char *question = NULL;
|
||||
@ -472,21 +516,21 @@ void layoutConfirmModifyFee(const CoinInfo *coin, uint64_t fee_old,
|
||||
question = _("Decrease your fee by:");
|
||||
fee_change = fee_old - fee_new;
|
||||
}
|
||||
bn_format_uint64(fee_change, NULL, coin->coin_shortcut, coin->decimals, 0,
|
||||
false, str_fee_change, sizeof(str_fee_change));
|
||||
format_coin_amount(fee_change, NULL, coin, amount_unit, str_fee_change,
|
||||
sizeof(str_fee_change));
|
||||
|
||||
bn_format_uint64(fee_new, NULL, coin->coin_shortcut, coin->decimals, 0, false,
|
||||
str_fee_new, sizeof(str_fee_new));
|
||||
format_coin_amount(fee_new, NULL, coin, amount_unit, str_fee_new,
|
||||
sizeof(str_fee_new));
|
||||
|
||||
layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), NULL,
|
||||
question, str_fee_change, NULL, _("Transaction fee:"),
|
||||
str_fee_new, NULL);
|
||||
}
|
||||
|
||||
void layoutFeeOverThreshold(const CoinInfo *coin, uint64_t fee) {
|
||||
void layoutFeeOverThreshold(const CoinInfo *coin, AmountUnit amount_unit,
|
||||
uint64_t fee) {
|
||||
char str_fee[32] = {0};
|
||||
bn_format_uint64(fee, NULL, coin->coin_shortcut, coin->decimals, 0, false,
|
||||
str_fee, sizeof(str_fee));
|
||||
format_coin_amount(fee, NULL, coin, amount_unit, str_fee, sizeof(str_fee));
|
||||
layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), NULL,
|
||||
_("Fee"), str_fee, _("is unexpectedly high."), NULL,
|
||||
_("Send anyway?"), NULL);
|
||||
|
@ -46,15 +46,18 @@ void layoutProgressSwipe(const char *desc, int permil);
|
||||
|
||||
void layoutScreensaver(void);
|
||||
void layoutHome(void);
|
||||
void layoutConfirmOutput(const CoinInfo *coin, const TxOutputType *out);
|
||||
void layoutConfirmOutput(const CoinInfo *coin, AmountUnit amount_unit,
|
||||
const TxOutputType *out);
|
||||
void layoutConfirmOmni(const uint8_t *data, uint32_t size);
|
||||
void layoutConfirmOpReturn(const uint8_t *data, uint32_t size);
|
||||
void layoutConfirmTx(const CoinInfo *coin, uint64_t total_in,
|
||||
uint64_t total_out, uint64_t change_out);
|
||||
void layoutConfirmTx(const CoinInfo *coin, AmountUnit amount_unit,
|
||||
uint64_t total_in, uint64_t total_out,
|
||||
uint64_t change_out);
|
||||
void layoutConfirmReplacement(const char *description, uint8_t txid[32]);
|
||||
void layoutConfirmModifyFee(const CoinInfo *coin, uint64_t fee_old,
|
||||
uint64_t fee_new);
|
||||
void layoutFeeOverThreshold(const CoinInfo *coin, uint64_t fee);
|
||||
void layoutConfirmModifyFee(const CoinInfo *coin, AmountUnit amount_unit,
|
||||
uint64_t fee_old, uint64_t fee_new);
|
||||
void layoutFeeOverThreshold(const CoinInfo *coin, AmountUnit amount_unit,
|
||||
uint64_t fee);
|
||||
void layoutChangeCountOverThreshold(uint32_t change_count);
|
||||
void layoutConfirmNondefaultLockTime(uint32_t lock_time,
|
||||
bool lock_time_disabled);
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
static uint32_t change_count;
|
||||
static const CoinInfo *coin;
|
||||
static AmountUnit amount_unit;
|
||||
static CONFIDENTIAL HDNode root;
|
||||
static CONFIDENTIAL HDNode node;
|
||||
static bool signing = false;
|
||||
@ -799,6 +800,7 @@ static bool tx_info_init(TxInfo *tx_info, uint32_t inputs_count,
|
||||
void signing_init(const SignTx *msg, const CoinInfo *_coin,
|
||||
const HDNode *_root) {
|
||||
coin = _coin;
|
||||
amount_unit = msg->has_amount_unit ? msg->amount_unit : AmountUnit_BITCOIN;
|
||||
memcpy(&root, _root, sizeof(HDNode));
|
||||
|
||||
if (!tx_info_init(&info, msg->inputs_count, msg->outputs_count, msg->version,
|
||||
@ -1229,7 +1231,8 @@ static bool signing_check_output(TxOutputType *txoutput) {
|
||||
// Skip confirmation of change-outputs and skip output confirmation altogether
|
||||
// in replacement transactions.
|
||||
bool skip_confirm = is_change || is_replacement;
|
||||
int co = compile_output(coin, &root, txoutput, &bin_output, !skip_confirm);
|
||||
int co = compile_output(coin, amount_unit, &root, txoutput, &bin_output,
|
||||
!skip_confirm);
|
||||
if (!skip_confirm) {
|
||||
layoutProgress(_("Signing transaction"), progress);
|
||||
}
|
||||
@ -1375,7 +1378,8 @@ static bool signing_check_orig_input(TxInputType *orig_input) {
|
||||
static bool signing_check_orig_output(TxOutputType *orig_output) {
|
||||
// Compute scriptPubKey.
|
||||
TxOutputBinType orig_bin_output;
|
||||
if (compile_output(coin, &root, orig_output, &orig_bin_output, false) <= 0) {
|
||||
if (compile_output(coin, amount_unit, &root, orig_output, &orig_bin_output,
|
||||
false) <= 0) {
|
||||
fsm_sendFailure(FailureType_Failure_ProcessError,
|
||||
_("Failed to compile output"));
|
||||
signing_abort();
|
||||
@ -1480,7 +1484,7 @@ static bool signing_confirm_tx(void) {
|
||||
if (total_out <= total_in) {
|
||||
fee = total_in - total_out;
|
||||
if (fee > ((uint64_t)tx_weight * coin->maxfee_kb) / 4000) {
|
||||
layoutFeeOverThreshold(coin, fee);
|
||||
layoutFeeOverThreshold(coin, amount_unit, fee);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_FeeOverThreshold,
|
||||
false)) {
|
||||
fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
|
||||
@ -1565,7 +1569,7 @@ static bool signing_confirm_tx(void) {
|
||||
|
||||
// Fee modification.
|
||||
if (fee != orig_fee) {
|
||||
layoutConfirmModifyFee(coin, orig_fee, fee);
|
||||
layoutConfirmModifyFee(coin, amount_unit, orig_fee, fee);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) {
|
||||
fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
|
||||
signing_abort();
|
||||
@ -1586,7 +1590,7 @@ static bool signing_confirm_tx(void) {
|
||||
}
|
||||
|
||||
// last confirmation
|
||||
layoutConfirmTx(coin, total_in, total_out, change_out);
|
||||
layoutConfirmTx(coin, amount_unit, total_in, total_out, change_out);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) {
|
||||
fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
|
||||
signing_abort();
|
||||
@ -2431,7 +2435,8 @@ void signing_txack(TransactionType *tx) {
|
||||
progress = 500 + ((signatures * progress_step +
|
||||
(info.inputs_count + idx2) * progress_meta_step) >>
|
||||
PROGRESS_PRECISION);
|
||||
if (compile_output(coin, &root, tx->outputs, &bin_output, false) <= 0) {
|
||||
if (compile_output(coin, amount_unit, &root, tx->outputs, &bin_output,
|
||||
false) <= 0) {
|
||||
fsm_sendFailure(FailureType_Failure_ProcessError,
|
||||
_("Failed to compile output"));
|
||||
signing_abort();
|
||||
@ -2573,7 +2578,8 @@ void signing_txack(TransactionType *tx) {
|
||||
if (!signing_validate_output(&tx->outputs[0])) {
|
||||
return;
|
||||
}
|
||||
if (compile_output(coin, &root, tx->outputs, &bin_output, false) <= 0) {
|
||||
if (compile_output(coin, amount_unit, &root, tx->outputs, &bin_output,
|
||||
false) <= 0) {
|
||||
fsm_sendFailure(FailureType_Failure_ProcessError,
|
||||
_("Failed to compile output"));
|
||||
signing_abort();
|
||||
|
@ -191,8 +191,9 @@ bool compute_address(const CoinInfo *coin, InputScriptType script_type,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int compile_output(const CoinInfo *coin, const HDNode *root, TxOutputType *in,
|
||||
TxOutputBinType *out, bool needs_confirm) {
|
||||
int compile_output(const CoinInfo *coin, AmountUnit amount_unit,
|
||||
const HDNode *root, TxOutputType *in, TxOutputBinType *out,
|
||||
bool needs_confirm) {
|
||||
memzero(out, sizeof(TxOutputBinType));
|
||||
out->amount = in->amount;
|
||||
out->decred_script_version = DECRED_SCRIPT_VERSION;
|
||||
@ -328,7 +329,7 @@ int compile_output(const CoinInfo *coin, const HDNode *root, TxOutputType *in,
|
||||
}
|
||||
|
||||
if (needs_confirm) {
|
||||
layoutConfirmOutput(coin, in);
|
||||
layoutConfirmOutput(coin, amount_unit, in);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return -1; // user aborted
|
||||
}
|
||||
|
@ -72,8 +72,9 @@ uint32_t serialize_script_sig(const uint8_t *signature, uint32_t signature_len,
|
||||
uint32_t serialize_script_multisig(const CoinInfo *coin,
|
||||
const MultisigRedeemScriptType *multisig,
|
||||
uint8_t sighash, uint8_t *out);
|
||||
int compile_output(const CoinInfo *coin, const HDNode *root, TxOutputType *in,
|
||||
TxOutputBinType *out, bool needs_confirm);
|
||||
int compile_output(const CoinInfo *coin, AmountUnit amount_unit,
|
||||
const HDNode *root, TxOutputType *in, TxOutputBinType *out,
|
||||
bool needs_confirm);
|
||||
|
||||
void tx_input_check_hash(Hasher *hasher, const TxInputType *input);
|
||||
uint32_t tx_prevout_hash(Hasher *hasher, const TxInputType *input);
|
||||
|
Loading…
Reference in New Issue
Block a user