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 "crypto.h"
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "address.h"
|
#include "address.h"
|
||||||
#include "aes/aes.h"
|
#include "aes/aes.h"
|
||||||
@ -368,6 +369,11 @@ uint32_t cryptoMultisigPubkeyCount(const MultisigRedeemScriptType *multisig) {
|
|||||||
: multisig->pubkeys_count;
|
: multisig->pubkeys_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int comparePubkeysLexicographically(const void *first,
|
||||||
|
const void *second) {
|
||||||
|
return memcmp(first, second, 33);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t cryptoMultisigPubkeys(const CoinInfo *coin,
|
uint32_t cryptoMultisigPubkeys(const CoinInfo *coin,
|
||||||
const MultisigRedeemScriptType *multisig,
|
const MultisigRedeemScriptType *multisig,
|
||||||
uint8_t *pubkeys) {
|
uint8_t *pubkeys) {
|
||||||
@ -384,6 +390,11 @@ uint32_t cryptoMultisigPubkeys(const CoinInfo *coin,
|
|||||||
memcpy(pubkeys + i * 33, pubnode->public_key, 33);
|
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;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,9 +410,14 @@ int cryptoMultisigPubkeyIndex(const CoinInfo *coin,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int comparePubnodesLexicographically(const void *first,
|
||||||
|
const void *second) {
|
||||||
|
return memcmp(first, second, sizeof(HDNodeType));
|
||||||
|
}
|
||||||
|
|
||||||
int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig,
|
int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig,
|
||||||
uint8_t *hash) {
|
uint8_t *hash) {
|
||||||
static const HDNodeType *pubnodes[15], *swap;
|
static const HDNodeType *pubnodes[15];
|
||||||
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
|
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
|
||||||
if (n < 1 || n > 15) {
|
if (n < 1 || n > 15) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -422,21 +438,20 @@ int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig,
|
|||||||
if (pubnodes[i]->public_key.size != 33) return 0;
|
if (pubnodes[i]->public_key.size != 33) return 0;
|
||||||
if (pubnodes[i]->chain_code.size != 32) return 0;
|
if (pubnodes[i]->chain_code.size != 32) return 0;
|
||||||
}
|
}
|
||||||
// minsort according to pubkey
|
|
||||||
for (uint32_t i = 0; i < n - 1; i++) {
|
if (multisig->has_pubkeys_order &&
|
||||||
for (uint32_t j = n - 1; j > i; j--) {
|
multisig->pubkeys_order == MultisigPubkeysOrder_LEXICOGRAPHIC) {
|
||||||
if (memcmp(pubnodes[i]->public_key.bytes, pubnodes[j]->public_key.bytes,
|
// If the order of pubkeys is lexicographic, we don't want the fingerprint
|
||||||
33) > 0) {
|
// to depend on the order of the pubnodes, so we sort the pubnodes before
|
||||||
swap = pubnodes[i];
|
// hashing.
|
||||||
pubnodes[i] = pubnodes[j];
|
qsort(pubnodes, n, sizeof(HDNodeType *), comparePubnodesLexicographically);
|
||||||
pubnodes[j] = swap;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
// hash sorted nodes
|
|
||||||
SHA256_CTX ctx = {0};
|
SHA256_CTX ctx = {0};
|
||||||
sha256_Init(&ctx);
|
sha256_Init(&ctx);
|
||||||
sha256_Update(&ctx, (const uint8_t *)&(multisig->m), sizeof(uint32_t));
|
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++) {
|
for (uint32_t i = 0; i < n; i++) {
|
||||||
sha256_Update(&ctx, (const uint8_t *)&(pubnodes[i]->depth),
|
sha256_Update(&ctx, (const uint8_t *)&(pubnodes[i]->depth),
|
||||||
sizeof(uint32_t));
|
sizeof(uint32_t));
|
||||||
|
@ -296,10 +296,15 @@ void fsm_msgGetAddress(const GetAddress *msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (msg->has_show_display && msg->show_display) {
|
if (msg->has_show_display && msg->show_display) {
|
||||||
char desc[20] = {0};
|
char desc[29] = {0};
|
||||||
int multisig_index = 0;
|
int multisig_index = 0;
|
||||||
if (msg->has_multisig) {
|
if (msg->has_multisig) {
|
||||||
|
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));
|
strlcpy(desc, "Multisig __ of __:", sizeof(desc));
|
||||||
|
}
|
||||||
const uint32_t m = msg->multisig.m;
|
const uint32_t m = msg->multisig.m;
|
||||||
const uint32_t n = cryptoMultisigPubkeyCount(&(msg->multisig));
|
const uint32_t n = cryptoMultisigPubkeyCount(&(msg->multisig));
|
||||||
desc[9] = (m < 10) ? ' ' : ('0' + (m / 10));
|
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,
|
uint32_t compile_script_multisig(const CoinInfo *coin,
|
||||||
const MultisigRedeemScriptType *multisig,
|
const MultisigRedeemScriptType *multisig,
|
||||||
uint8_t *out) {
|
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 m = multisig->m;
|
||||||
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
|
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
|
||||||
if (m < 1 || m > 15) return 0;
|
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,
|
uint32_t compile_script_multisig_hash(const CoinInfo *coin,
|
||||||
const MultisigRedeemScriptType *multisig,
|
const MultisigRedeemScriptType *multisig,
|
||||||
uint8_t *hash) {
|
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 m = multisig->m;
|
||||||
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
|
const uint32_t n = cryptoMultisigPubkeyCount(multisig);
|
||||||
if (m < 1 || m > 15) return 0;
|
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,
|
uint32_t serialize_script_multisig(const CoinInfo *coin,
|
||||||
const MultisigRedeemScriptType *multisig,
|
const MultisigRedeemScriptType *multisig,
|
||||||
uint8_t sighash, uint8_t *out) {
|
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;
|
uint32_t r = 0;
|
||||||
#if !BITCOIN_ONLY
|
#if !BITCOIN_ONLY
|
||||||
if (!coin->decred) {
|
if (!coin->decred) {
|
||||||
|
@ -197,7 +197,6 @@ def test_altcoin_address_mac(client: Client):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.multisig
|
@pytest.mark.multisig
|
||||||
@pytest.mark.models(skip="legacy", reason="Sortedmulti is not supported")
|
|
||||||
def test_multisig_pubkeys_order(client: Client):
|
def test_multisig_pubkeys_order(client: Client):
|
||||||
xpub_internal = btc.get_public_node(client, parse_path("m/45h/0")).xpub
|
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
|
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.multisig
|
||||||
@pytest.mark.models(skip="legacy", reason="Sortedmulti is not supported")
|
|
||||||
def test_pubkeys_order(client: Client):
|
def test_pubkeys_order(client: Client):
|
||||||
node_internal = btc.get_public_node(
|
node_internal = btc.get_public_node(
|
||||||
client, parse_path("m/45h/0"), coin_name="Bitcoin"
|
client, parse_path("m/45h/0"), coin_name="Bitcoin"
|
||||||
|
Loading…
Reference in New Issue
Block a user