parent
c2c0900c5d
commit
0f07d74063
@ -0,0 +1 @@
|
||||
Signed Ethereum network and token definitions from host
|
@ -1,7 +1,8 @@
|
||||
coin_info.[ch]
|
||||
nem_mosaics.[ch]
|
||||
ethereum_networks.h
|
||||
ethereum_tokens.[ch]
|
||||
ethereum_definitions_constants.h
|
||||
ethereum_networks.c
|
||||
ethereum_tokens.c
|
||||
u2f_knownapps.h
|
||||
|
||||
bl_data.h
|
||||
|
@ -0,0 +1,313 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (C) 2022 Martin Novak <martin.novak@satoshilabs.com>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "crypto.h"
|
||||
#include "ethereum.h"
|
||||
#include "ethereum_definitions.h"
|
||||
#include "ethereum_definitions_constants.h"
|
||||
#include "ethereum_networks.h"
|
||||
#include "ethereum_tokens.h"
|
||||
#include "fsm.h"
|
||||
#include "gettext.h"
|
||||
#include "memzero.h"
|
||||
#include "messages.h"
|
||||
#include "pb.h"
|
||||
#include "pb_decode.h"
|
||||
#include "trezor.h" // because of the "VERSTR" macro used in "fsm_sendFailureDebug" function
|
||||
#include "util.h"
|
||||
|
||||
typedef pb_byte_t proof_entry[SHA256_DIGEST_LENGTH];
|
||||
|
||||
struct EncodedDefinition {
|
||||
// prefix
|
||||
pb_byte_t format_version[FORMAT_VERSION_LENGTH];
|
||||
uint8_t definition_type;
|
||||
uint32_t data_version;
|
||||
uint16_t payload_length;
|
||||
|
||||
// payload
|
||||
const pb_byte_t *payload;
|
||||
|
||||
// suffix
|
||||
uint8_t proof_length;
|
||||
const proof_entry *proof;
|
||||
|
||||
const ed25519_signature *signed_root_hash;
|
||||
};
|
||||
|
||||
static bool parse_encoded_definition(struct EncodedDefinition *const result,
|
||||
const pb_size_t size,
|
||||
const pb_byte_t *bytes) {
|
||||
// format version + definition type + data version + payload length + payload
|
||||
// (at least 1B) + proof length + signed Merkle tree root hash
|
||||
if (size < (FORMAT_VERSION_LENGTH + 1 + 4 + 2 + 1 + 1 +
|
||||
MERKLE_TREE_SIGNED_ROOT_SIZE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const pb_byte_t *cursor = bytes;
|
||||
memcpy(result->format_version, cursor, FORMAT_VERSION_LENGTH);
|
||||
cursor += FORMAT_VERSION_LENGTH;
|
||||
|
||||
result->definition_type = *cursor;
|
||||
cursor += 1;
|
||||
|
||||
result->data_version = *(uint32_t *)cursor;
|
||||
cursor += 4;
|
||||
|
||||
result->payload_length = *(uint16_t *)cursor;
|
||||
cursor += 2;
|
||||
|
||||
result->payload = cursor;
|
||||
cursor += result->payload_length;
|
||||
|
||||
if (size <= cursor - bytes) {
|
||||
return false;
|
||||
}
|
||||
result->proof_length = *cursor;
|
||||
cursor += 1;
|
||||
|
||||
// check the whole size of incoming bytes array
|
||||
if (size != (cursor - bytes) + result->proof_length * sizeof(proof_entry) +
|
||||
MERKLE_TREE_SIGNED_ROOT_SIZE) {
|
||||
return false;
|
||||
}
|
||||
result->proof = (proof_entry *)cursor;
|
||||
cursor += result->proof_length * sizeof(proof_entry);
|
||||
|
||||
result->signed_root_hash = (ed25519_signature *)cursor;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool decode_definition(const pb_size_t size, const pb_byte_t *bytes,
|
||||
const EthereumDefinitionType expected_type,
|
||||
void *definition) {
|
||||
// parse received definition
|
||||
static struct EncodedDefinition parsed_def;
|
||||
const char *error_str = _("Invalid Ethereum definition");
|
||||
|
||||
memzero(&parsed_def, sizeof(parsed_def));
|
||||
if (!parse_encoded_definition(&parsed_def, size, bytes)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
// check definition fields
|
||||
if (memcmp(FORMAT_VERSION, parsed_def.format_version,
|
||||
FORMAT_VERSION_LENGTH)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (expected_type != parsed_def.definition_type) {
|
||||
error_str = _("Definition type mismatch");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (MIN_DATA_VERSION > parsed_def.data_version) {
|
||||
error_str = _("Definition is outdated");
|
||||
goto err;
|
||||
}
|
||||
|
||||
// compute Merkle tree root hash from proof
|
||||
uint8_t hash[SHA256_DIGEST_LENGTH] = {0};
|
||||
SHA256_CTX context = {0};
|
||||
sha256_Init(&context);
|
||||
|
||||
// leaf hash = sha256('\x00' + leaf data)
|
||||
sha256_Update(&context, (uint8_t[]){0}, 1);
|
||||
// signed data is everything from start of `bytes` to the end of `payload`
|
||||
const pb_byte_t *payload_end = parsed_def.payload + parsed_def.payload_length;
|
||||
size_t signed_data_size = payload_end - bytes;
|
||||
sha256_Update(&context, bytes, signed_data_size);
|
||||
|
||||
sha256_Final(&context, hash);
|
||||
|
||||
const uint8_t *min, *max;
|
||||
for (uint8_t i = 0; i < parsed_def.proof_length; i++) {
|
||||
sha256_Init(&context);
|
||||
// node hash = sha256('\x01' + min(hash, next_proof) + max(hash,
|
||||
// next_proof))
|
||||
sha256_Update(&context, (uint8_t[]){1}, 1);
|
||||
if (memcmp(hash, parsed_def.proof[i], SHA256_DIGEST_LENGTH) <= 0) {
|
||||
min = hash;
|
||||
max = parsed_def.proof[i];
|
||||
} else {
|
||||
min = parsed_def.proof[i];
|
||||
max = hash;
|
||||
}
|
||||
sha256_Update(&context, min, SHA256_DIGEST_LENGTH);
|
||||
sha256_Update(&context, max, SHA256_DIGEST_LENGTH);
|
||||
sha256_Final(&context, hash);
|
||||
}
|
||||
|
||||
// and verify its signature
|
||||
if (ed25519_sign_open(hash, SHA256_DIGEST_LENGTH, DEFINITIONS_PUBLIC_KEY,
|
||||
*(parsed_def.signed_root_hash)) != 0
|
||||
#if DEBUG_LINK
|
||||
&&
|
||||
ed25519_sign_open(hash, SHA256_DIGEST_LENGTH, DEFINITIONS_DEV_PUBLIC_KEY,
|
||||
*(parsed_def.signed_root_hash)) != 0
|
||||
#endif
|
||||
) {
|
||||
// invalid signature
|
||||
error_str = _("Invalid definition signature");
|
||||
goto err;
|
||||
}
|
||||
|
||||
// decode message
|
||||
const pb_msgdesc_t *fields = (expected_type == EthereumDefinitionType_NETWORK
|
||||
? EthereumNetworkInfo_fields
|
||||
: EthereumTokenInfo_fields);
|
||||
pb_istream_t stream =
|
||||
pb_istream_from_buffer(parsed_def.payload, parsed_def.payload_length);
|
||||
bool status = pb_decode(&stream, fields, definition);
|
||||
if (status) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// fallthrough to error handling in case of decoding failure
|
||||
|
||||
err:
|
||||
memzero(&parsed_def, sizeof(parsed_def));
|
||||
fsm_sendFailure(FailureType_Failure_DataError, error_str);
|
||||
return false;
|
||||
}
|
||||
|
||||
static const EthereumNetworkInfo *get_network(
|
||||
const EncodedNetwork *encoded_network, const uint64_t chain_id,
|
||||
const uint32_t slip44) {
|
||||
static EthereumNetworkInfo decoded_network;
|
||||
const EthereumNetworkInfo *network = &UNKNOWN_NETWORK;
|
||||
|
||||
// try to get built-in definition
|
||||
if (chain_id != CHAIN_ID_UNKNOWN) {
|
||||
network = ethereum_get_network_by_chain_id(chain_id);
|
||||
} else if (slip44 != SLIP44_UNKNOWN) {
|
||||
network = ethereum_get_network_by_slip44(slip44);
|
||||
} else {
|
||||
// if both chain_id and slip44 is unspecified, we do not have anything to
|
||||
// match to the encoded definition, so just short-circuit here
|
||||
return &UNKNOWN_NETWORK;
|
||||
}
|
||||
// if we found built-in definition, or if there's no data to decode, we are
|
||||
// done
|
||||
if (!is_unknown_network(network) || encoded_network == NULL) {
|
||||
return network;
|
||||
}
|
||||
|
||||
// if we still do not have any network definition try to decode received data
|
||||
memzero(&decoded_network, sizeof(decoded_network));
|
||||
if (!decode_definition(encoded_network->size, encoded_network->bytes,
|
||||
EthereumDefinitionType_NETWORK, &decoded_network)) {
|
||||
// error already sent by decode_definition
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (chain_id != CHAIN_ID_UNKNOWN && decoded_network.chain_id != chain_id) {
|
||||
fsm_sendFailure(FailureType_Failure_DataError,
|
||||
_("Network definition mismatch"));
|
||||
return NULL;
|
||||
}
|
||||
if (slip44 != SLIP44_UNKNOWN && decoded_network.slip44 != slip44) {
|
||||
fsm_sendFailure(FailureType_Failure_DataError,
|
||||
_("Network definition mismatch"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &decoded_network;
|
||||
}
|
||||
|
||||
static const EthereumTokenInfo *get_token(const EncodedToken *encoded_token,
|
||||
const uint64_t chain_id,
|
||||
const char *address) {
|
||||
static EthereumTokenInfo decoded_token;
|
||||
|
||||
// if we do not know the chain_id, we cannot get the token
|
||||
if (chain_id == CHAIN_ID_UNKNOWN) {
|
||||
return &UNKNOWN_TOKEN;
|
||||
}
|
||||
|
||||
// convert address string to bytes
|
||||
EthereumTokenInfo_address_t address_bytes;
|
||||
bool address_parsed = address && ethereum_parse(address, address_bytes.bytes);
|
||||
if (!address_parsed) {
|
||||
// without a valid address, we cannot get the token
|
||||
return &UNKNOWN_TOKEN;
|
||||
}
|
||||
|
||||
// try to get built-in definition
|
||||
const EthereumTokenInfo *token =
|
||||
ethereum_token_by_address(chain_id, address_bytes.bytes);
|
||||
if (!is_unknown_token(token) || encoded_token == NULL) {
|
||||
// if we found one, or if there's no data to decode, we are done
|
||||
return token;
|
||||
}
|
||||
|
||||
// try to decode received definition
|
||||
memzero(&decoded_token, sizeof(decoded_token));
|
||||
if (!decode_definition(encoded_token->size, encoded_token->bytes,
|
||||
EthereumDefinitionType_TOKEN, &decoded_token)) {
|
||||
// error already sent by decode_definition
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (decoded_token.chain_id != chain_id ||
|
||||
memcmp(decoded_token.address.bytes, address_bytes.bytes,
|
||||
sizeof(decoded_token.address.bytes))) {
|
||||
// receiving a mismatched token is not an error (we expect being able to get
|
||||
// multiple token definitions in the future, for multiple networks)
|
||||
// but we must not accept the mismatched definition
|
||||
memzero(&decoded_token, sizeof(decoded_token));
|
||||
return &UNKNOWN_TOKEN;
|
||||
}
|
||||
|
||||
return &decoded_token;
|
||||
}
|
||||
|
||||
const EthereumDefinitionsDecoded *ethereum_get_definitions(
|
||||
const EncodedNetwork *encoded_network, const EncodedToken *encoded_token,
|
||||
const uint64_t chain_id, const uint32_t slip44, const char *token_address) {
|
||||
static EthereumDefinitionsDecoded defs;
|
||||
memzero(&defs, sizeof(defs));
|
||||
|
||||
const EthereumNetworkInfo *network =
|
||||
get_network(encoded_network, chain_id, slip44);
|
||||
if (network == NULL) {
|
||||
// error while decoding, failure was sent by get_network
|
||||
return NULL;
|
||||
}
|
||||
defs.network = network;
|
||||
|
||||
if (!is_unknown_network(network) && token_address != NULL) {
|
||||
const EthereumTokenInfo *token =
|
||||
get_token(encoded_token, network->chain_id, token_address);
|
||||
if (token == NULL) {
|
||||
// error while decoding, failure was sent by get_token
|
||||
return NULL;
|
||||
}
|
||||
defs.token = token;
|
||||
} else {
|
||||
defs.token = &UNKNOWN_TOKEN;
|
||||
}
|
||||
|
||||
return &defs;
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (C) 2022 Martin Novak <martin.novak@satoshilabs.com>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ETHEREUM_DEFINITIONS_H__
|
||||
#define __ETHEREUM_DEFINITIONS_H__
|
||||
|
||||
#include "messages-ethereum-definitions.pb.h"
|
||||
|
||||
typedef EthereumDefinitions_encoded_network_t EncodedNetwork;
|
||||
typedef EthereumDefinitions_encoded_token_t EncodedToken;
|
||||
|
||||
typedef struct {
|
||||
const EthereumNetworkInfo *network;
|
||||
const EthereumTokenInfo *token;
|
||||
} EthereumDefinitionsDecoded;
|
||||
|
||||
const EthereumDefinitionsDecoded *ethereum_get_definitions(
|
||||
const EncodedNetwork *encoded_network, const EncodedToken *encoded_token,
|
||||
const uint64_t chain_id, const uint32_t slip44, const char *token_address);
|
||||
|
||||
#endif
|
@ -0,0 +1,26 @@
|
||||
// This file is automatically generated from ethereum_definitions_constants.h.mako
|
||||
// DO NOT EDIT
|
||||
|
||||
#ifndef __ETHEREUM_DEFINITIONS_CONSTANTS_H__
|
||||
#define __ETHEREUM_DEFINITIONS_CONSTANTS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "crypto.h"
|
||||
#include "messages-ethereum-definitions.pb.h"
|
||||
#include "pb.h"
|
||||
|
||||
static const uint8_t DEFINITIONS_PUBLIC_KEY[] =
|
||||
" "; // TODO: update
|
||||
#if DEBUG_LINK
|
||||
static const uint8_t DEFINITIONS_DEV_PUBLIC_KEY[] =
|
||||
"\xdb\x99\x5f\xe2\x51\x69\xd1\x41\xca\xb9\xbb\xba\x92\xba\xa0\x1f\x9f\x2e"
|
||||
"\x1e\xce\x7d\xf4\xcb\x2a\xc0\x51\x90\xf3\x7f\xcc\x1f\x9d";
|
||||
#endif
|
||||
|
||||
#define MIN_DATA_VERSION ${ethereum_defs_timestamp}
|
||||
#define FORMAT_VERSION_LENGTH 5
|
||||
#define FORMAT_VERSION (const pb_byte_t *)"trzd1"
|
||||
#define MERKLE_TREE_SIGNED_ROOT_SIZE sizeof(ed25519_signature)
|
||||
|
||||
#endif
|
@ -0,0 +1,48 @@
|
||||
<% networks = list(supported_on("trezor1", eth)) %>\
|
||||
// This file is automatically generated from ethereum_networks.c.mako
|
||||
// DO NOT EDIT
|
||||
|
||||
#include "ethereum.h"
|
||||
#include "ethereum_networks.h"
|
||||
|
||||
#define NETWORKS_COUNT ${len(networks)}
|
||||
|
||||
static const EthereumNetworkInfo networks[NETWORKS_COUNT] = {
|
||||
% for n in networks:
|
||||
{
|
||||
.chain_id = ${n.chain_id},
|
||||
.slip44 = ${n.slip44},
|
||||
.symbol = ${c_str(n.shortcut)}, /* ${n.name} */
|
||||
.name = "",
|
||||
},
|
||||
% endfor
|
||||
};
|
||||
|
||||
const EthereumNetworkInfo UNKNOWN_NETWORK = {
|
||||
.chain_id = CHAIN_ID_UNKNOWN,
|
||||
.slip44 = SLIP44_UNKNOWN,
|
||||
.symbol = "UNKN",
|
||||
.name = "",
|
||||
};
|
||||
|
||||
const EthereumNetworkInfo *ethereum_get_network_by_chain_id(uint64_t chain_id) {
|
||||
for (size_t i = 0; i < NETWORKS_COUNT; i++) {
|
||||
if (networks[i].chain_id == chain_id) {
|
||||
return &networks[i];
|
||||
}
|
||||
}
|
||||
return &UNKNOWN_NETWORK;
|
||||
}
|
||||
|
||||
const EthereumNetworkInfo *ethereum_get_network_by_slip44(uint32_t slip44) {
|
||||
for (size_t i = 0; i < NETWORKS_COUNT; i++) {
|
||||
if (networks[i].slip44 == slip44) {
|
||||
return &networks[i];
|
||||
}
|
||||
}
|
||||
return &UNKNOWN_NETWORK;
|
||||
}
|
||||
|
||||
bool is_unknown_network(const EthereumNetworkInfo *network) {
|
||||
return network->chain_id == CHAIN_ID_UNKNOWN;
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (C) 2018 Pavol Rusnak <stick@satoshilabs.com>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ETHEREUM_NETWORKS_H__
|
||||
#define __ETHEREUM_NETWORKS_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "messages-ethereum-definitions.pb.h"
|
||||
|
||||
extern const EthereumNetworkInfo UNKNOWN_NETWORK;
|
||||
#define SLIP44_UNKNOWN UINT32_MAX
|
||||
|
||||
const EthereumNetworkInfo *ethereum_get_network_by_chain_id(uint64_t chain_id);
|
||||
const EthereumNetworkInfo *ethereum_get_network_by_slip44(uint32_t slip44);
|
||||
bool is_unknown_network(const EthereumNetworkInfo *network);
|
||||
|
||||
#endif
|
@ -1,61 +0,0 @@
|
||||
<%
|
||||
BKSL = "\\"
|
||||
|
||||
networks = list(supported_on("trezor1", eth))
|
||||
max_chain_id_length = 0
|
||||
max_slip44_length = 0
|
||||
max_suffix_length = 0
|
||||
for n in networks:
|
||||
max_chain_id_length = max(len(str(n.chain_id)), max_chain_id_length)
|
||||
max_slip44_length = max(len(str(n.slip44)), max_slip44_length)
|
||||
max_suffix_length = max(len(n.shortcut), max_suffix_length)
|
||||
|
||||
def align_chain_id(n):
|
||||
return "{:>{w}}".format(n.chain_id, w=max_chain_id_length)
|
||||
|
||||
def align_slip44(n):
|
||||
return "{:>{w}}".format(n.slip44, w=max_slip44_length)
|
||||
|
||||
def align_suffix(n):
|
||||
cstr = c_str(" " + n.shortcut) + ";"
|
||||
# we add two quotes, a space and a semicolon. hence +4 chars
|
||||
return "{:<{w}}".format(cstr, w=max_suffix_length + 4)
|
||||
|
||||
%>\
|
||||
// This file is automatically generated from ethereum_networks.h.mako
|
||||
// DO NOT EDIT
|
||||
|
||||
#ifndef __ETHEREUM_NETWORKS_H__
|
||||
#define __ETHEREUM_NETWORKS_H__
|
||||
|
||||
#define SLIP44_UNKNOWN UINT32_MAX
|
||||
|
||||
#define ASSIGN_ETHEREUM_SUFFIX(suffix, chain_id) ${BKSL}
|
||||
switch (chain_id) { ${BKSL}
|
||||
% for n in networks:
|
||||
case ${align_chain_id(n)}: suffix = ${align_suffix(n)} break; /* ${n.name} */ ${BKSL}
|
||||
% endfor
|
||||
default: suffix = " UNKN"; break; /* unknown chain */ ${BKSL}
|
||||
}
|
||||
|
||||
static bool is_ethereum_slip44(uint32_t slip44) {
|
||||
switch (slip44) {
|
||||
% for slip44 in sorted(set(n.slip44 for n in networks)):
|
||||
case ${slip44}:
|
||||
% endfor
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t ethereum_slip44_by_chain_id(uint64_t chain_id) {
|
||||
switch (chain_id) {
|
||||
% for n in networks:
|
||||
case ${align_chain_id(n)}: return ${align_slip44(n)}; /* ${n.name} */
|
||||
% endfor
|
||||
default: return SLIP44_UNKNOWN; /* unknown chain */
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (C) 2023 Trezor Company s.r.o.
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ETHEREUM_TOKENS_H__
|
||||
#define __ETHEREUM_TOKENS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ethereum_definitions.h"
|
||||
|
||||
extern const EthereumTokenInfo UNKNOWN_TOKEN;
|
||||
|
||||
const EthereumTokenInfo *ethereum_token_by_address(uint64_t chain_id,
|
||||
const uint8_t *address);
|
||||
bool is_unknown_token(const EthereumTokenInfo *token);
|
||||
|
||||
#endif
|
@ -1,25 +0,0 @@
|
||||
// This file is automatically generated from ethereum_tokens.h.mako
|
||||
// DO NOT EDIT
|
||||
|
||||
#ifndef __ETHEREUM_TOKENS_H__
|
||||
#define __ETHEREUM_TOKENS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
<% erc20_list = list(supported_on("trezor1", erc20)) %>\
|
||||
#define TOKENS_COUNT ${len(erc20_list)}
|
||||
|
||||
typedef struct {
|
||||
uint64_t chain_id;
|
||||
const char * const address;
|
||||
const char * const ticker;
|
||||
int decimals;
|
||||
} TokenType;
|
||||
|
||||
extern const TokenType tokens[TOKENS_COUNT];
|
||||
|
||||
extern const TokenType *UnknownToken;
|
||||
|
||||
const TokenType *tokenByChainAddress(uint64_t chain_id, const uint8_t *address);
|
||||
|
||||
#endif
|
@ -0,0 +1,9 @@
|
||||
EthereumNetworkInfo.name max_size:256
|
||||
EthereumNetworkInfo.symbol max_size:256
|
||||
|
||||
EthereumTokenInfo.name max_size:256
|
||||
EthereumTokenInfo.address max_size:20
|
||||
EthereumTokenInfo.symbol max_size:256
|
||||
|
||||
EthereumDefinitions.encoded_network max_size:1024
|
||||
EthereumDefinitions.encoded_token max_size:1024
|
@ -0,0 +1 @@
|
||||
../../vendor/trezor-common/protob/messages-ethereum-definitions.proto
|
Loading…
Reference in new issue