diff --git a/firmware/fsm.c b/firmware/fsm.c index 4740c93d9..4a97c39b3 100644 --- a/firmware/fsm.c +++ b/firmware/fsm.c @@ -611,6 +611,9 @@ void fsm_msgGetAddress(GetAddress *msg) if (!node) return; hdnode_fill_public_key(node); int is_segwit = 0; + uint8_t digest[32]; + uint8_t raw[32+2+4]; + size_t prelen; if (msg->has_multisig) { layoutProgressSwipe("Preparing", 0); @@ -619,20 +622,45 @@ void fsm_msgGetAddress(GetAddress *msg) layoutHome(); return; } - uint8_t buf[32]; - if (compile_script_multisig_hash(&(msg->multisig), buf) == 0) { + if (compile_script_multisig_hash(&(msg->multisig), digest) == 0) { fsm_sendFailure(FailureType_Failure_Other, "Invalid multisig script"); layoutHome(); return; } - ripemd160(buf, 32, buf + 1); - buf[0] = coin->address_type_p2sh; // multisig cointype - base58_encode_check(buf, 21, resp->address, sizeof(resp->address)); + if (msg->has_script_type + && (msg->script_type == InputScriptType_SPENDWITNESS + || msg->script_type == InputScriptType_SPENDP2SHWITNESS)) { + is_segwit = 1; + // segwit p2wsh: script hash is single sha256 + if (msg->script_type == InputScriptType_SPENDWITNESS) { + prelen = address_prefix_bytes_len(coin->address_type_p2wsh); + address_write_prefix_bytes(coin->address_type_p2wsh, raw); + raw[prelen] = 0; // version byte + raw[prelen + 1] = 0; // always 0, see bip-142 + memcpy(raw+prelen+2, digest, 32); + base58_encode_check(raw, prelen + 34, resp->address, sizeof(resp->address)); + } else { + // segwit p2wsh encapsuled in p2sh address + raw[0] = 0; // push version + raw[1] = 32; // push 32 bytes + memcpy(raw+2, digest, 32); // push hash + sha256_Raw(raw, 34, digest); + prelen = address_prefix_bytes_len(coin->address_type_p2wsh); + address_write_prefix_bytes(coin->address_type_p2sh, raw); + ripemd160(digest, 32, raw + prelen); + base58_encode_check(raw, prelen + 20, resp->address, sizeof(resp->address)); + } + } else { + // non-segwit p2sh multisig + prelen = address_prefix_bytes_len(coin->address_type_p2sh); + address_write_prefix_bytes(coin->address_type_p2sh, raw); + ripemd160(digest, 32, raw + prelen); + base58_encode_check(raw, prelen + 20, resp->address, sizeof(resp->address)); + } } else if (msg->has_script_type && msg->script_type == InputScriptType_SPENDWITNESS && coin->has_address_type_p2wpkh) { - uint8_t raw[22+4]; - int prelen = address_prefix_bytes_len(coin->address_type_p2wpkh); + prelen = address_prefix_bytes_len(coin->address_type_p2wpkh); address_write_prefix_bytes(coin->address_type_p2wpkh, raw); raw[prelen] = 0; // version byte raw[prelen + 1] = 0; // always 0, see bip-142 @@ -646,16 +674,14 @@ void fsm_msgGetAddress(GetAddress *msg) } else if (msg->has_script_type && msg->script_type == InputScriptType_SPENDP2SHWITNESS && coin->has_address_type_p2sh) { - uint8_t script[22]; - uint8_t digest[32]; - int prelen = address_prefix_bytes_len(coin->address_type_p2sh); - script[0] = 0; // version byte - script[1] = 20; // push 20 bytes - ecdsa_get_pubkeyhash(node->public_key, script + 2); - sha256_Raw(script, 22, digest); - ripemd160(digest, 32, digest + prelen); - address_write_prefix_bytes(coin->address_type_p2sh, digest); - if (!base58_encode_check(digest, 21, resp->address, sizeof(resp->address))) { + prelen = address_prefix_bytes_len(coin->address_type_p2sh); + raw[0] = 0; // version byte + raw[1] = 20; // push 20 bytes + ecdsa_get_pubkeyhash(node->public_key, raw + 2); + sha256_Raw(raw, 22, digest); + address_write_prefix_bytes(coin->address_type_p2sh, raw); + ripemd160(digest, 32, raw + prelen); + if (!base58_encode_check(raw, 21, resp->address, sizeof(resp->address))) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Can't encode address"); layoutHome(); return; diff --git a/firmware/layout2.c b/firmware/layout2.c index 6a7612062..5862a95ad 100644 --- a/firmware/layout2.c +++ b/firmware/layout2.c @@ -245,6 +245,7 @@ void layoutAddress(const char *address, const char *desc) static unsigned char bitdata[QR_MAX_BITDATA]; int a, i, j; int side = qr_encode(QR_LEVEL_M, 0, address, 0, bitdata); + int startx; if (side > 0 && side <= 29) { oledInvert(0, 0, (side + 2) * 2, (side + 2) * 2); @@ -259,6 +260,20 @@ void layoutAddress(const char *address, const char *desc) } } } + startx = 68; + } else if (side > 0 && side <= 60) { + oledInvert(0, 0, (side + 3), (side + 3)); + for (i = 0; i < side; i++) { + for (j = 0; j< side; j++) { + a = j * side + i; + if (bitdata[a / 8] & (1 << (7 - a % 8))) { + oledClearPixel(2 + i, 2 + j); + } + } + } + startx = side + 6; + } else { + startx = 0; } uint32_t addrlen = strlen(address); @@ -269,12 +284,11 @@ void layoutAddress(const char *address, const char *desc) const char **str = split_message((const uint8_t *)address, addrlen, rowlen); if (desc) { - oledDrawString(68, 0 * 9, desc); + oledDrawString(startx, 0 * 9, desc); + } + for (i = 0; i < 4; i++) { + oledDrawString(startx, (i+1) * 9 + 4, str[i]); } - oledDrawString(68, 1 * 9 + 4, str[0]); - oledDrawString(68, 2 * 9 + 4, str[1]); - oledDrawString(68, 3 * 9 + 4, str[2]); - oledDrawString(68, 4 * 9 + 4, str[3]); static const char *btnYes = "Continue"; oledDrawString(OLED_WIDTH - fontCharWidth('\x06') - 1, OLED_HEIGHT - 8, "\x06"); diff --git a/firmware/protob/messages.pb.h b/firmware/protob/messages.pb.h index 7123f4495..2b19e7eda 100644 --- a/firmware/protob/messages.pb.h +++ b/firmware/protob/messages.pb.h @@ -130,7 +130,7 @@ typedef struct _WordRequest { } WordRequest; typedef struct _Address { - char address[41]; + char address[60]; } Address; typedef struct { @@ -1242,7 +1242,7 @@ extern const pb_field_t DebugLinkFlashErase_fields[2]; #define PublicKey_size (121 + HDNodeType_size) #define GetAddress_size (81 + MultisigRedeemScriptType_size) #define EthereumGetAddress_size 50 -#define Address_size 43 +#define Address_size 62 #define EthereumAddress_size 22 #define WipeDevice_size 0 #define LoadDevice_size (326 + HDNodeType_size)