mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-30 19:38:15 +00:00
feat(legacy): support sortedmulti
This commit is contained in:
parent
f3c85e7ec7
commit
2322c6774d
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "crypto.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "address.h"
|
||||
#include "aes/aes.h"
|
||||
@ -368,6 +369,11 @@ uint32_t cryptoMultisigPubkeyCount(const MultisigRedeemScriptType *multisig) {
|
||||
: multisig->pubkeys_count;
|
||||
}
|
||||
|
||||
static int comparePubkeysLexicographically(const void *first,
|
||||
const void *second) {
|
||||
return memcmp(first, second, 33);
|
||||
}
|
||||
|
||||
uint32_t cryptoMultisigPubkeys(const CoinInfo *coin,
|
||||
const MultisigRedeemScriptType *multisig,
|
||||
uint8_t *pubkeys) {
|
||||
@ -384,6 +390,11 @@ uint32_t cryptoMultisigPubkeys(const CoinInfo *coin,
|
||||
memcpy(pubkeys + i * 33, pubnode->public_key, 33);
|
||||
}
|
||||
|
||||
if (multisig->has_pubkeys_order &&
|
||||
multisig->pubkeys_order == MultisigPubkeysOrder_LEXICOGRAPHIC) {
|
||||
qsort(pubkeys, n, 33, comparePubkeysLexicographically);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@ -399,9 +410,14 @@ int cryptoMultisigPubkeyIndex(const CoinInfo *coin,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int comparePubnodesLexicographically(const void *first,
|
||||
const void *second) {
|
||||
return memcmp(first, second, sizeof(HDNodeType));
|
||||
}
|
||||
|
||||
int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig,
|
||||
uint8_t *hash) {
|
||||
static const HDNodeType *pubnodes[15], *swap;
|
||||
static const HDNodeType *pubnodes[15];
|
||||
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
|
||||
if (n < 1 || n > 15) {
|
||||
return 0;
|
||||
@ -422,21 +438,20 @@ int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig,
|
||||
if (pubnodes[i]->public_key.size != 33) return 0;
|
||||
if (pubnodes[i]->chain_code.size != 32) return 0;
|
||||
}
|
||||
// minsort according to pubkey
|
||||
for (uint32_t i = 0; i < n - 1; i++) {
|
||||
for (uint32_t j = n - 1; j > i; j--) {
|
||||
if (memcmp(pubnodes[i]->public_key.bytes, pubnodes[j]->public_key.bytes,
|
||||
33) > 0) {
|
||||
swap = pubnodes[i];
|
||||
pubnodes[i] = pubnodes[j];
|
||||
pubnodes[j] = swap;
|
||||
}
|
||||
}
|
||||
|
||||
if (multisig->has_pubkeys_order &&
|
||||
multisig->pubkeys_order == MultisigPubkeysOrder_LEXICOGRAPHIC) {
|
||||
// If the order of pubkeys is lexicographic, we don't want the fingerprint
|
||||
// to depend on the order of the pubnodes, so we sort the pubnodes before
|
||||
// hashing.
|
||||
qsort(pubnodes, n, sizeof(HDNodeType *), comparePubnodesLexicographically);
|
||||
}
|
||||
// hash sorted nodes
|
||||
|
||||
SHA256_CTX ctx = {0};
|
||||
sha256_Init(&ctx);
|
||||
sha256_Update(&ctx, (const uint8_t *)&(multisig->m), sizeof(uint32_t));
|
||||
sha256_Update(&ctx, (const uint8_t *)&(multisig->pubkeys_order),
|
||||
sizeof(uint32_t));
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
sha256_Update(&ctx, (const uint8_t *)&(pubnodes[i]->depth),
|
||||
sizeof(uint32_t));
|
||||
|
@ -296,10 +296,15 @@ void fsm_msgGetAddress(const GetAddress *msg) {
|
||||
}
|
||||
|
||||
if (msg->has_show_display && msg->show_display) {
|
||||
char desc[20] = {0};
|
||||
char desc[29] = {0};
|
||||
int multisig_index = 0;
|
||||
if (msg->has_multisig) {
|
||||
strlcpy(desc, "Multisig __ of __:", sizeof(desc));
|
||||
if (msg->multisig.has_pubkeys_order &&
|
||||
msg->multisig.pubkeys_order == MultisigPubkeysOrder_LEXICOGRAPHIC) {
|
||||
strlcpy(desc, "Multisig __ of __ (sorted):", sizeof(desc));
|
||||
} else {
|
||||
strlcpy(desc, "Multisig __ of __:", sizeof(desc));
|
||||
}
|
||||
const uint32_t m = msg->multisig.m;
|
||||
const uint32_t n = cryptoMultisigPubkeyCount(&(msg->multisig));
|
||||
desc[9] = (m < 10) ? ' ' : ('0' + (m / 10));
|
||||
|
@ -364,11 +364,6 @@ uint32_t compile_script_sig(uint32_t address_type, const uint8_t *pubkeyhash,
|
||||
uint32_t compile_script_multisig(const CoinInfo *coin,
|
||||
const MultisigRedeemScriptType *multisig,
|
||||
uint8_t *out) {
|
||||
if (multisig->pubkeys_order != MultisigPubkeysOrder_PRESERVED) {
|
||||
fsm_sendFailure(FailureType_Failure_DataError,
|
||||
_("Sortedmulti is not supported"));
|
||||
return 0;
|
||||
}
|
||||
const uint32_t m = multisig->m;
|
||||
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
|
||||
if (m < 1 || m > 15) return 0;
|
||||
@ -402,12 +397,6 @@ uint32_t compile_script_multisig(const CoinInfo *coin,
|
||||
uint32_t compile_script_multisig_hash(const CoinInfo *coin,
|
||||
const MultisigRedeemScriptType *multisig,
|
||||
uint8_t *hash) {
|
||||
if (multisig->pubkeys_order != MultisigPubkeysOrder_PRESERVED) {
|
||||
fsm_sendFailure(FailureType_Failure_DataError,
|
||||
_("Sortedmulti is not supported"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint32_t m = multisig->m;
|
||||
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
|
||||
if (m < 1 || m > 15) return 0;
|
||||
@ -457,11 +446,6 @@ 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) {
|
||||
if (multisig->pubkeys_order != MultisigPubkeysOrder_PRESERVED) {
|
||||
fsm_sendFailure(FailureType_Failure_DataError,
|
||||
_("Sortedmulti is not supported"));
|
||||
return 0;
|
||||
}
|
||||
uint32_t r = 0;
|
||||
#if !BITCOIN_ONLY
|
||||
if (!coin->decred) {
|
||||
|
@ -197,7 +197,6 @@ def test_altcoin_address_mac(client: Client):
|
||||
|
||||
|
||||
@pytest.mark.multisig
|
||||
@pytest.mark.models(skip="legacy", reason="Sortedmulti is not supported")
|
||||
def test_multisig_pubkeys_order(client: Client):
|
||||
xpub_internal = btc.get_public_node(client, parse_path("m/45h/0")).xpub
|
||||
xpub_external = btc.get_public_node(client, parse_path("m/44h/1")).xpub
|
||||
|
@ -162,7 +162,6 @@ def test_2_of_3(client: Client, chunkify: bool):
|
||||
|
||||
|
||||
@pytest.mark.multisig
|
||||
@pytest.mark.models(skip="legacy", reason="Sortedmulti is not supported")
|
||||
def test_pubkeys_order(client: Client):
|
||||
node_internal = btc.get_public_node(
|
||||
client, parse_path("m/45h/0"), coin_name="Bitcoin"
|
||||
|
Loading…
Reference in New Issue
Block a user