New CoinInfo separated from protobuf structures

Having CoinType using the protobuf structures has several disadvantages.
- We always need to change trezor-common if we need a new field (like
  bech32 prefix)
- Every time Trezor initializes it sends all this information out and
  nobody cares.
- The protobuf structures add storage overhead due to their fixed size.

I also removed most of the `has_` fields except for forkid:
- `has_segwit` was merged with segwit
- `has_coin_shortcut` can be replaced by test for NULL if necessary.

The fields were reordered for better padding.
pull/25/head
Jochen Hoenicke 7 years ago committed by Pavol Rusnak
parent 18d8cb3c56
commit b5fa8a266a

@ -13,34 +13,18 @@ if len(sys.argv) != 2 or sys.argv[1] not in ("count", "array"):
def get_fields(coin):
return [
'true' if coin['coin_name'] is not None else 'false',
'"%s"' % coin['coin_name'] if coin['coin_name'] is not None else 'NULL',
'true' if coin['coin_shortcut'] is not None else 'false',
'" %s"' % coin['coin_shortcut'] if coin['coin_shortcut'] is not None else 'NULL',
'true' if coin['address_type'] is not None else 'false',
'%d' % coin['address_type'] if coin['address_type'] is not None else '0',
'true' if coin['maxfee_kb'] is not None else 'false',
'%d' % coin['maxfee_kb'] if coin['maxfee_kb'] is not None else '0',
'"\\x%02x" "%s"' % (len(coin['signed_message_header']), coin['signed_message_header'].replace('\n', '\\n')) if coin['signed_message_header'] is not None else 'NULL',
'true' if coin['address_type'] is not None else 'false',
'true' if coin['address_type_p2sh'] is not None else 'false',
'true' if coin['segwit'] else 'false',
'true' if coin['forkid'] is not None else 'false',
'%d' % coin['address_type'] if coin['address_type'] is not None else '0',
'%d' % coin['address_type_p2sh'] if coin['address_type_p2sh'] is not None else '0',
'true' if coin['signed_message_header'] is not None else 'false',
'"\\x%02x" "%s"' % (len(coin['signed_message_header']), coin['signed_message_header'].replace('\n', '\\n')) if coin['signed_message_header'] is not None else 'NULL',
'true' if coin['xpub_magic'] is not None else 'false',
'0x%s' % coin['xpub_magic'] if coin['xpub_magic'] is not None else '00000000',
'true' if coin['xprv_magic'] is not None else 'false',
'0x%s' % coin['xprv_magic'] if coin['xprv_magic'] is not None else '00000000',
'true' if coin['segwit'] is not None else 'false',
'true' if coin['segwit'] else 'false',
'true' if coin['forkid'] is not None else 'false',
'%d' % coin['forkid'] if coin['forkid'] else '0'
]

@ -23,13 +23,12 @@
#include "ecdsa.h"
#include "base58.h"
// filled CoinType Protobuf structure defined in https://github.com/trezor/trezor-common/blob/master/protob/types.proto#L133
// address types > 0xFF represent a two-byte prefix in big-endian order
const CoinType coins[COINS_COUNT] = {
// filled CoinInfo structure defined in coins.h
const CoinInfo coins[COINS_COUNT] = {
#include "coins_array.h"
};
const CoinType *coinByName(const char *name)
const CoinInfo *coinByName(const char *name)
{
if (!name) return 0;
for (int i = 0; i < COINS_COUNT; i++) {
@ -40,7 +39,7 @@ const CoinType *coinByName(const char *name)
return 0;
}
const CoinType *coinByAddressType(uint32_t address_type)
const CoinInfo *coinByAddressType(uint32_t address_type)
{
for (int i = 0; i < COINS_COUNT; i++) {
if (address_type == coins[i].address_type) {
@ -50,7 +49,7 @@ const CoinType *coinByAddressType(uint32_t address_type)
return 0;
}
bool coinExtractAddressType(const CoinType *coin, const char *addr, uint32_t *address_type)
bool coinExtractAddressType(const CoinInfo *coin, const char *addr, uint32_t *address_type)
{
if (!addr) return false;
uint8_t addr_raw[MAX_ADDR_RAW_SIZE];
@ -61,7 +60,7 @@ bool coinExtractAddressType(const CoinType *coin, const char *addr, uint32_t *ad
return false;
}
bool coinExtractAddressTypeRaw(const CoinType *coin, const uint8_t *addr_raw, uint32_t *address_type)
bool coinExtractAddressTypeRaw(const CoinInfo *coin, const uint8_t *addr_raw, uint32_t *address_type)
{
if (coin->has_address_type && address_check_prefix(addr_raw, coin->address_type)) {
*address_type = coin->address_type;

@ -20,17 +20,33 @@
#ifndef __COINS_H__
#define __COINS_H__
#include "messages.pb.h"
#include <stdint.h>
#include <stdbool.h>
#include "coins_count.h"
_Static_assert(pb_arraysize(Features, coins) >= COINS_COUNT, "Features.coins max_count not large enough");
typedef struct _CoinInfo {
const char *coin_name;
const char *coin_shortcut;
uint64_t maxfee_kb;
const char *signed_message_header;
bool has_address_type;
bool has_address_type_p2sh;
bool has_segwit;
bool has_forkid;
// address types > 0xFF represent a two-byte prefix in big-endian order
uint32_t address_type;
uint32_t address_type_p2sh;
uint32_t xpub_magic;
uint32_t xprv_magic;
uint32_t forkid;
} CoinInfo;
extern const CoinType coins[COINS_COUNT];
extern const CoinInfo coins[COINS_COUNT];
const CoinType *coinByName(const char *name);
const CoinType *coinByAddressType(uint32_t address_type);
bool coinExtractAddressType(const CoinType *coin, const char *addr, uint32_t *address_type);
bool coinExtractAddressTypeRaw(const CoinType *coin, const uint8_t *addr_raw, uint32_t *address_type);
const CoinInfo *coinByName(const char *name);
const CoinInfo *coinByAddressType(uint32_t address_type);
bool coinExtractAddressType(const CoinInfo *coin, const char *addr, uint32_t *address_type);
bool coinExtractAddressTypeRaw(const CoinInfo *coin, const uint8_t *addr_raw, uint32_t *address_type);
#endif

@ -110,7 +110,7 @@ int gpgMessageSign(HDNode *node, const uint8_t *message, size_t message_len, uin
}
}
int cryptoMessageSign(const CoinType *coin, HDNode *node, InputScriptType script_type, const uint8_t *message, size_t message_len, uint8_t *signature)
int cryptoMessageSign(const CoinInfo *coin, HDNode *node, InputScriptType script_type, const uint8_t *message, size_t message_len, uint8_t *signature)
{
SHA256_CTX ctx;
sha256_Init(&ctx);
@ -143,7 +143,7 @@ int cryptoMessageSign(const CoinType *coin, HDNode *node, InputScriptType script
return result;
}
int cryptoMessageVerify(const CoinType *coin, const uint8_t *message, size_t message_len, uint32_t address_type, const uint8_t *address_raw, const uint8_t *signature)
int cryptoMessageVerify(const CoinInfo *coin, const uint8_t *message, size_t message_len, uint32_t address_type, const uint8_t *address_raw, const uint8_t *signature)
{
// check for invalid signature prefix
if (signature[0] < 27 || signature[0] > 43) {

@ -27,6 +27,7 @@
#include <bip32.h>
#include <sha2.h>
#include <pb.h>
#include "coins.h"
#include "types.pb.h"
uint32_t ser_length(uint32_t len, uint8_t *out);
@ -37,9 +38,9 @@ int sshMessageSign(HDNode *node, const uint8_t *message, size_t message_len, uin
int gpgMessageSign(HDNode *node, const uint8_t *message, size_t message_len, uint8_t *signature);
int cryptoMessageSign(const CoinType *coin, HDNode *node, InputScriptType script_type, const uint8_t *message, size_t message_len, uint8_t *signature);
int cryptoMessageSign(const CoinInfo *coin, HDNode *node, InputScriptType script_type, const uint8_t *message, size_t message_len, uint8_t *signature);
int cryptoMessageVerify(const CoinType *coin, const uint8_t *message, size_t message_len, uint32_t address_type, const uint8_t *address_raw, const uint8_t *signature);
int cryptoMessageVerify(const CoinInfo *coin, const uint8_t *message, size_t message_len, uint32_t address_type, const uint8_t *address_raw, const uint8_t *signature);
/* ECIES disabled
int cryptoMessageEncrypt(curve_point *pubkey, const uint8_t *msg, size_t msg_size, bool display_only, uint8_t *nonce, size_t *nonce_len, uint8_t *payload, size_t *payload_len, uint8_t *hmac, size_t *hmac_len, const uint8_t *privkey, const uint8_t *address_raw);

@ -163,9 +163,9 @@ void fsm_sendFailure(FailureType code, const char *text)
msg_write(MessageType_MessageType_Failure, resp);
}
const CoinType *fsm_getCoin(bool has_name, const char *name)
const CoinInfo *fsm_getCoin(bool has_name, const char *name)
{
const CoinType *coin;
const CoinInfo *coin;
if (has_name) {
coin = coinByName(name);
} else {
@ -208,6 +208,8 @@ void fsm_msgInitialize(Initialize *msg)
fsm_msgGetFeatures(0);
}
_Static_assert(pb_arraysize(Features, coins) >= COINS_COUNT, "Features.coins max_count not large enough");
void fsm_msgGetFeatures(GetFeatures *msg)
{
(void)msg;
@ -233,7 +235,12 @@ void fsm_msgGetFeatures(GetFeatures *msg)
strlcpy(resp->label, storage.label, sizeof(resp->label));
}
resp->coins_count = COINS_COUNT;
memcpy(resp->coins, coins, COINS_COUNT * sizeof(CoinType));
for (int i = 0; i < COINS_COUNT; i++) {
resp->coins[i].has_coin_name = true;
strlcpy(resp->coins[i].coin_name, coins[i].coin_name, sizeof(resp->coins[i].coin_name));
resp->coins[i].has_maxfee_kb = true;
resp->coins[i].maxfee_kb = coins[i].maxfee_kb;
}
resp->has_initialized = true; resp->initialized = storage_isInitialized();
resp->has_imported = true; resp->imported = storage.has_imported && storage.imported;
resp->has_pin_cached = true; resp->pin_cached = session_isPinCached();
@ -358,7 +365,7 @@ void fsm_msgGetPublicKey(GetPublicKey *msg)
CHECK_PIN
const CoinType *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name);
const CoinInfo *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name);
if (!coin) return;
const char *curve = SECP256K1_NAME;
@ -471,7 +478,7 @@ void fsm_msgSignTx(SignTx *msg)
CHECK_PIN
const CoinType *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name);
const CoinInfo *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name);
if (!coin) return;
const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, 0, 0);
if (!node) return;
@ -640,7 +647,7 @@ void fsm_msgGetAddress(GetAddress *msg)
CHECK_PIN
const CoinType *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name);
const CoinInfo *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name);
if (!coin) return;
HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count);
if (!node) return;
@ -794,7 +801,7 @@ void fsm_msgSignMessage(SignMessage *msg)
CHECK_PIN
const CoinType *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name);
const CoinInfo *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name);
if (!coin) return;
HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count);
if (!node) return;
@ -822,7 +829,7 @@ void fsm_msgVerifyMessage(VerifyMessage *msg)
CHECK_PARAM(msg->has_address, _("No address provided"));
CHECK_PARAM(msg->has_message, _("No message provided"));
const CoinType *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name);
const CoinInfo *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name);
if (!coin) return;
uint8_t addr_raw[MAX_ADDR_RAW_SIZE];
uint32_t address_type;
@ -992,7 +999,7 @@ void fsm_msgEncryptMessage(EncryptMessage *msg)
const HDNode *node = 0;
uint8_t address_raw[MAX_ADDR_RAW_SIZE];
if (signing) {
const CoinType *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name);
const CoinInfo *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name);
if (!coin) return;
CHECK_PIN

@ -97,10 +97,10 @@ void layoutHome(void)
system_millis_lock_start = system_millis;
}
void layoutConfirmOutput(const CoinType *coin, const TxOutputType *out)
void layoutConfirmOutput(const CoinInfo *coin, const TxOutputType *out)
{
char str_out[32];
bn_format_uint64(out->amount, NULL, coin->has_coin_shortcut ? coin->coin_shortcut : NULL, BITCOIN_DIVISIBILITY, 0, false, str_out, sizeof(str_out));
bn_format_uint64(out->amount, NULL, coin->coin_shortcut, BITCOIN_DIVISIBILITY, 0, false, str_out, sizeof(str_out));
static char first_half[17 + 1];
strlcpy(first_half, out->address, sizeof(first_half));
layoutDialogSwipe(&bmp_icon_question,
@ -116,11 +116,11 @@ void layoutConfirmOutput(const CoinType *coin, const TxOutputType *out)
);
}
void layoutConfirmTx(const CoinType *coin, uint64_t amount_out, uint64_t amount_fee)
void layoutConfirmTx(const CoinInfo *coin, uint64_t amount_out, uint64_t amount_fee)
{
char str_out[32], str_fee[32];
bn_format_uint64(amount_out, NULL, coin->has_coin_shortcut ? coin->coin_shortcut : NULL, BITCOIN_DIVISIBILITY, 0, false, str_out, sizeof(str_out));
bn_format_uint64(amount_fee, NULL, coin->has_coin_shortcut ? coin->coin_shortcut : NULL, BITCOIN_DIVISIBILITY, 0, false, str_fee, sizeof(str_fee));
bn_format_uint64(amount_out, NULL, coin->coin_shortcut, BITCOIN_DIVISIBILITY, 0, false, str_out, sizeof(str_out));
bn_format_uint64(amount_fee, NULL, coin->coin_shortcut, BITCOIN_DIVISIBILITY, 0, false, str_fee, sizeof(str_fee));
layoutDialogSwipe(&bmp_icon_question,
_("Cancel"),
_("Confirm"),
@ -134,10 +134,10 @@ void layoutConfirmTx(const CoinType *coin, uint64_t amount_out, uint64_t amount_
);
}
void layoutFeeOverThreshold(const CoinType *coin, uint64_t fee)
void layoutFeeOverThreshold(const CoinInfo *coin, uint64_t fee)
{
char str_fee[32];
bn_format_uint64(fee, NULL, coin->has_coin_shortcut ? coin->coin_shortcut : NULL, BITCOIN_DIVISIBILITY, 0, false, str_fee, sizeof(str_fee));
bn_format_uint64(fee, NULL, coin->coin_shortcut, BITCOIN_DIVISIBILITY, 0, false, str_fee, sizeof(str_fee));
layoutDialogSwipe(&bmp_icon_question,
_("Cancel"),
_("Confirm"),

@ -22,6 +22,7 @@
#include "layout.h"
#include "types.pb.h"
#include "coins.h"
#include "bitmaps.h"
#include "bignum.h"
#include "trezor.h"
@ -39,9 +40,9 @@ void layoutProgressSwipe(const char *desc, int permil);
void layoutScreensaver(void);
void layoutHome(void);
void layoutConfirmOutput(const CoinType *coin, const TxOutputType *out);
void layoutConfirmTx(const CoinType *coin, uint64_t amount_out, uint64_t amount_fee);
void layoutFeeOverThreshold(const CoinType *coin, uint64_t fee);
void layoutConfirmOutput(const CoinInfo *coin, const TxOutputType *out);
void layoutConfirmTx(const CoinInfo *coin, uint64_t amount_out, uint64_t amount_fee);
void layoutFeeOverThreshold(const CoinInfo *coin, uint64_t fee);
void layoutSignMessage(const uint8_t *msg, uint32_t len);
void layoutVerifyAddress(const char *address);
void layoutVerifyMessage(const uint8_t *msg, uint32_t len);

@ -30,7 +30,7 @@
static uint32_t inputs_count;
static uint32_t outputs_count;
static const CoinType *coin;
static const CoinInfo *coin;
static const HDNode *root;
static CONFIDENTIAL HDNode node;
static bool signing = false;
@ -424,7 +424,7 @@ bool compile_input_script_sig(TxInputType *tinput)
return tinput->script_sig.size > 0;
}
void signing_init(uint32_t _inputs_count, uint32_t _outputs_count, const CoinType *_coin, const HDNode *_root, uint32_t _version, uint32_t _lock_time)
void signing_init(uint32_t _inputs_count, uint32_t _outputs_count, const CoinInfo *_coin, const HDNode *_root, uint32_t _version, uint32_t _lock_time)
{
inputs_count = _inputs_count;
outputs_count = _outputs_count;
@ -827,7 +827,7 @@ void signing_txack(TransactionType *tx)
}
} else if (tx->inputs[0].script_type == InputScriptType_SPENDWITNESS
|| tx->inputs[0].script_type == InputScriptType_SPENDP2SHWITNESS) {
if (!coin->has_segwit || !coin->segwit) {
if (!coin->has_segwit) {
fsm_sendFailure(FailureType_Failure_DataError, _("Segwit not enabled on this coin"));
signing_abort();
return;

@ -23,9 +23,10 @@
#include <stdint.h>
#include <stdbool.h>
#include "bip32.h"
#include "coins.h"
#include "types.pb.h"
void signing_init(uint32_t _inputs_count, uint32_t _outputs_count, const CoinType *_coin, const HDNode *_root, uint32_t _version, uint32_t _lock_time);
void signing_init(uint32_t _inputs_count, uint32_t _outputs_count, const CoinInfo *_coin, const HDNode *_root, uint32_t _version, uint32_t _lock_time);
void signing_abort(void);
void signing_txack(TransactionType *tx);

@ -58,7 +58,7 @@ uint32_t op_push(uint32_t i, uint8_t *out) {
return 5;
}
bool compute_address(const CoinType *coin,
bool compute_address(const CoinInfo *coin,
InputScriptType script_type,
const HDNode *node,
bool has_multisig, const MultisigRedeemScriptType *multisig,
@ -77,14 +77,14 @@ bool compute_address(const CoinType *coin,
}
if (script_type == InputScriptType_SPENDWITNESS) {
// segwit p2wsh: script hash is single sha256
if (!coin->has_segwit || !coin->segwit) {
if (!coin->has_segwit) {
return 0;
}
// disable native segwit for now
return 0;
} else if (script_type == InputScriptType_SPENDP2SHWITNESS) {
// segwit p2wsh encapsuled in p2sh address
if (!coin->has_segwit || !coin->segwit) {
if (!coin->has_segwit) {
return 0;
}
if (!coin->has_address_type_p2sh) {
@ -111,14 +111,14 @@ bool compute_address(const CoinType *coin,
}
} else if (script_type == InputScriptType_SPENDWITNESS) {
// segwit p2wpkh: pubkey hash is ripemd160 of sha256
if (!coin->has_segwit || !coin->segwit) {
if (!coin->has_segwit) {
return 0;
}
// disable native segwit for now
return 0;
} else if (script_type == InputScriptType_SPENDP2SHWITNESS) {
// segwit p2wpkh embedded in p2sh
if (!coin->has_segwit || !coin->segwit) {
if (!coin->has_segwit) {
return 0;
}
if (!coin->has_address_type_p2sh) {
@ -131,7 +131,7 @@ bool compute_address(const CoinType *coin,
return 1;
}
int compile_output(const CoinType *coin, const HDNode *root, TxOutputType *in, TxOutputBinType *out, bool needs_confirm)
int compile_output(const CoinInfo *coin, const HDNode *root, TxOutputType *in, TxOutputBinType *out, bool needs_confirm)
{
memset(out, 0, sizeof(TxOutputBinType));
out->amount = in->amount;

@ -24,6 +24,7 @@
#include <stdint.h>
#include "sha2.h"
#include "bip32.h"
#include "coins.h"
#include "types.pb.h"
typedef struct {
@ -45,13 +46,13 @@ typedef struct {
SHA256_CTX ctx;
} TxStruct;
bool compute_address(const CoinType *coin, InputScriptType script_type, const HDNode *node, bool has_multisig, const MultisigRedeemScriptType *multisig, char address[MAX_ADDR_SIZE]);
bool compute_address(const CoinInfo *coin, InputScriptType script_type, const HDNode *node, bool has_multisig, const MultisigRedeemScriptType *multisig, char address[MAX_ADDR_SIZE]);
uint32_t compile_script_sig(uint32_t address_type, const uint8_t *pubkeyhash, uint8_t *out);
uint32_t compile_script_multisig(const MultisigRedeemScriptType *multisig, uint8_t *out);
uint32_t compile_script_multisig_hash(const MultisigRedeemScriptType *multisig, uint8_t *hash);
uint32_t serialize_script_sig(const uint8_t *signature, uint32_t signature_len, const uint8_t *pubkey, uint32_t pubkey_len, uint8_t sighash, uint8_t *out);
uint32_t serialize_script_multisig(const MultisigRedeemScriptType *multisig, uint8_t sighash, uint8_t *out);
int compile_output(const CoinType *coin, const HDNode *root, TxOutputType *in, TxOutputBinType *out, bool needs_confirm);
int compile_output(const CoinInfo *coin, const HDNode *root, TxOutputType *in, TxOutputBinType *out, bool needs_confirm);
uint32_t tx_prevout_hash(SHA256_CTX *ctx, const TxInputType *input);
uint32_t tx_script_hash(SHA256_CTX *ctx, uint32_t size, const uint8_t *data);

Loading…
Cancel
Save