Indicate own dest address in send dialog

If the destination address is controlled by the TREZOR (the wallet set
the address_n field), show the path to the address on the confirm output
dialog in the same format as the "show on Trezor" dialog indicates the
path.
This commit is contained in:
Jochen Hoenicke 2018-03-02 18:00:10 +01:00 committed by Pavol Rusnak
parent e460c4fe17
commit d5e49556c5
1 changed files with 121 additions and 117 deletions

View File

@ -36,6 +36,122 @@
#define BITCOIN_DIVISIBILITY (8)
static const char *slip44_extras(uint32_t coin_type)
{
if ((coin_type & 0x80000000) == 0) {
return 0;
}
switch (coin_type & 0x7fffffff) {
case 40: return "EXP"; // Expanse
case 43: return "NEM"; // NEM
case 60: return "ETH"; // Ethereum Mainnet
case 61: return "ETC"; // Ethereum Classic Mainnet
case 108: return "UBQ"; // UBIQ
case 137: return "RSK"; // Rootstock Mainnet
case 37310: return "tRSK"; // Rootstock Testnet
}
return 0;
}
#define BIP32_MAX_LAST_ELEMENT 1000000
static const char *address_n_str(const uint32_t *address_n, size_t address_n_count)
{
if (address_n_count > 8) {
return _("Unknown long path");
}
if (address_n_count == 0) {
return _("Path: m");
}
// known BIP44/49 path
static char path[100];
if (address_n_count == 5 &&
(address_n[0] == (0x80000000 + 44) || address_n[0] == (0x80000000 + 49) || address_n[0] == (0x80000000 + 84)) &&
(address_n[1] & 0x80000000) &&
(address_n[2] & 0x80000000) &&
(address_n[3] <= 1) &&
(address_n[4] <= BIP32_MAX_LAST_ELEMENT)) {
bool native_segwit = (address_n[0] == (0x80000000 + 84));
bool p2sh_segwit = (address_n[0] == (0x80000000 + 49));
bool legacy = false;
const CoinInfo *coin = coinByCoinType(address_n[1]);
const char *abbr = 0;
if (native_segwit) {
if (coin && coin->has_segwit && coin->bech32_prefix) {
abbr = coin->coin_shortcut + 1;
}
} else
if (p2sh_segwit) {
if (coin && coin->has_segwit && coin->has_address_type_p2sh) {
abbr = coin->coin_shortcut + 1;
}
} else {
if (coin) {
if (coin->has_segwit && coin->has_address_type_p2sh) {
legacy = true;
}
abbr = coin->coin_shortcut + 1;
} else {
abbr = slip44_extras(address_n[1]);
}
}
uint32_t accnum = (address_n[2] & 0x7fffffff) + 1;
if (abbr && accnum < 100) {
memset(path, 0, sizeof(path));
strlcpy(path, abbr, sizeof(path));
// TODO: how to name accounts?
// currently we have "legacy account", "account" and "segwit account"
// for BIP44/P2PKH, BIP49/P2SH-P2WPKH and BIP84/P2WPKH respectivelly
if (legacy) {
strlcat(path, " legacy", sizeof(path));
}
if (native_segwit) {
strlcat(path, " segwit", sizeof(path));
}
strlcat(path, " account #", sizeof(path));
char acc[3];
memset(acc, 0, sizeof(acc));
if (accnum < 10) {
acc[0] = '0' + accnum;
} else {
acc[0] = '0' + (accnum / 10);
acc[1] = '0' + (accnum % 10);
}
strlcat(path, acc, sizeof(path));
return path;
}
}
// "Path: m" / i '
static char address_str[7 + 8 * (1 + 9 + 1) + 1];
char *c = address_str + sizeof(address_str) - 1;
*c = 0; c--;
for (int n = (int)address_n_count - 1; n >= 0; n--) {
uint32_t i = address_n[n];
if (i & 0x80000000) {
*c = '\''; c--;
}
i = i & 0x7fffffff;
do {
*c = '0' + (i % 10); c--;
i /= 10;
} while (i > 0);
*c = '/'; c--;
}
*c = 'm'; c--;
*c = ' '; c--;
*c = ':'; c--;
*c = 'h'; c--;
*c = 't'; c--;
*c = 'a'; c--;
*c = 'P';
return c;
}
// split longer string into 4 rows, rowlen chars each
static const char **split_message(const uint8_t *msg, uint32_t len, uint32_t rowlen)
{
@ -149,7 +265,11 @@ void layoutConfirmOutput(const CoinInfo *coin, const TxOutputType *out)
oledDrawString(left, 4 * 9, str[2], FONT_FIXED);
oledDrawString(left, 5 * 9, str[3], FONT_FIXED);
if (!str[3][0]) {
oledHLine(OLED_HEIGHT - 13);
if (out->address_n_count > 0) {
oledDrawString(0, 5*9, address_n_str(out->address_n, out->address_n_count), FONT_STANDARD);
} else {
oledHLine(OLED_HEIGHT - 13);
}
}
layoutButtonNo(_("Cancel"));
layoutButtonYes(_("Confirm"));
@ -324,122 +444,6 @@ void layoutResetWord(const char *word, int pass, int word_pos, bool last)
oledRefresh();
}
static const char *slip44_extras(uint32_t coin_type)
{
if ((coin_type & 0x80000000) == 0) {
return 0;
}
switch (coin_type & 0x7fffffff) {
case 40: return "EXP"; // Expanse
case 43: return "NEM"; // NEM
case 60: return "ETH"; // Ethereum Mainnet
case 61: return "ETC"; // Ethereum Classic Mainnet
case 108: return "UBQ"; // UBIQ
case 137: return "RSK"; // Rootstock Mainnet
case 37310: return "tRSK"; // Rootstock Testnet
}
return 0;
}
#define BIP32_MAX_LAST_ELEMENT 1000000
static const char *address_n_str(const uint32_t *address_n, size_t address_n_count)
{
if (address_n_count > 8) {
return _("Unknown long path");
}
if (address_n_count == 0) {
return _("Path: m");
}
// known BIP44/49 path
static char path[100];
if (address_n_count == 5 &&
(address_n[0] == (0x80000000 + 44) || address_n[0] == (0x80000000 + 49) || address_n[0] == (0x80000000 + 84)) &&
(address_n[1] & 0x80000000) &&
(address_n[2] & 0x80000000) &&
(address_n[3] <= 1) &&
(address_n[4] <= BIP32_MAX_LAST_ELEMENT)) {
bool native_segwit = (address_n[0] == (0x80000000 + 84));
bool p2sh_segwit = (address_n[0] == (0x80000000 + 49));
bool legacy = false;
const CoinInfo *coin = coinByCoinType(address_n[1]);
const char *abbr = 0;
if (native_segwit) {
if (coin && coin->has_segwit && coin->bech32_prefix) {
abbr = coin->coin_shortcut + 1;
}
} else
if (p2sh_segwit) {
if (coin && coin->has_segwit && coin->has_address_type_p2sh) {
abbr = coin->coin_shortcut + 1;
}
} else {
if (coin) {
if (coin->has_segwit && coin->has_address_type_p2sh) {
legacy = true;
}
abbr = coin->coin_shortcut + 1;
} else {
abbr = slip44_extras(address_n[1]);
}
}
uint32_t accnum = (address_n[2] & 0x7fffffff) + 1;
if (abbr && accnum < 100) {
memset(path, 0, sizeof(path));
strlcpy(path, abbr, sizeof(path));
// TODO: how to name accounts?
// currently we have "legacy account", "account" and "segwit account"
// for BIP44/P2PKH, BIP49/P2SH-P2WPKH and BIP84/P2WPKH respectivelly
if (legacy) {
strlcat(path, " legacy", sizeof(path));
}
if (native_segwit) {
strlcat(path, " segwit", sizeof(path));
}
strlcat(path, " account #", sizeof(path));
char acc[3];
memset(acc, 0, sizeof(acc));
if (accnum < 10) {
acc[0] = '0' + accnum;
} else {
acc[0] = '0' + (accnum / 10);
acc[1] = '0' + (accnum % 10);
}
strlcat(path, acc, sizeof(path));
return path;
}
}
// "Path: m" / i '
static char address_str[7 + 8 * (1 + 9 + 1) + 1];
char *c = address_str + sizeof(address_str) - 1;
*c = 0; c--;
for (int n = (int)address_n_count - 1; n >= 0; n--) {
uint32_t i = address_n[n];
if (i & 0x80000000) {
*c = '\''; c--;
}
i = i & 0x7fffffff;
do {
*c = '0' + (i % 10); c--;
i /= 10;
} while (i > 0);
*c = '/'; c--;
}
*c = 'm'; c--;
*c = ' '; c--;
*c = ':'; c--;
*c = 'h'; c--;
*c = 't'; c--;
*c = 'a'; c--;
*c = 'P';
return c;
}
void layoutAddress(const char *address, const char *desc, bool qrcode, bool ignorecase, const uint32_t *address_n, size_t address_n_count)
{
if (layoutLast != layoutAddress) {