feat(legacy): implement amount_unit for SignTx

pull/1426/head
Pavol Rusnak 3 years ago committed by Tomas Susanka
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…
Cancel
Save