mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-22 15:38:11 +00:00
nem_mosaics: Initial commit
This commit is contained in:
parent
4a55dd89e6
commit
8dbd6182fb
@ -25,6 +25,7 @@ OBJS += crypto.o
|
||||
OBJS += ethereum.o
|
||||
OBJS += ethereum_tokens.o
|
||||
OBJS += nem2.o
|
||||
OBJS += nem_mosaics.o
|
||||
|
||||
OBJS += debug.o
|
||||
|
||||
|
@ -30,8 +30,8 @@
|
||||
#include "qr_encode.h"
|
||||
#include "timer.h"
|
||||
#include "bignum.h"
|
||||
#include "nem.h"
|
||||
#include "secp256k1.h"
|
||||
#include "nem2.h"
|
||||
#include "gettext.h"
|
||||
|
||||
#define BITCOIN_DIVISIBILITY (8)
|
||||
@ -468,18 +468,7 @@ void layoutU2FDialog(const char *verb, const char *appname, const BITMAP *appico
|
||||
layoutDialog(appicon, NULL, verb, NULL, verb, _("U2F security key?"), NULL, appname, NULL, NULL);
|
||||
}
|
||||
|
||||
static inline void nemFormatAmount(bignum256 *amnt, uint64_t quantity, int divisibility, const bignum256 *mul, const char *ticker, char *str_out, size_t size) {
|
||||
bn_read_uint64(quantity, amnt);
|
||||
|
||||
if (mul) {
|
||||
bn_multiply(mul, amnt, &secp256k1.prime);
|
||||
bn_format(amnt, NULL, ticker, divisibility + NEM_XEM_DIVISIBILITY, str_out, size);
|
||||
} else {
|
||||
bn_format(amnt, NULL, ticker, divisibility, str_out, size);
|
||||
}
|
||||
}
|
||||
|
||||
void layoutNEMDialog(const BITMAP *icon, const char *btnNo, const char *btnYes, const char *desc, const char *line1, const char *address, const char *line5, const char *line6) {
|
||||
void layoutNEMDialog(const BITMAP *icon, const char *btnNo, const char *btnYes, const char *desc, const char *line1, const char *address) {
|
||||
static char first_third[NEM_ADDRESS_SIZE / 3 + 1];
|
||||
strlcpy(first_third, address, sizeof(first_third));
|
||||
|
||||
@ -496,18 +485,16 @@ void layoutNEMDialog(const BITMAP *icon, const char *btnNo, const char *btnYes,
|
||||
first_third,
|
||||
second_third,
|
||||
third_third,
|
||||
line5,
|
||||
line6);
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void layoutNEMTransferXEM(const char *desc, uint64_t quantity, const bignum256 *mul, uint64_t fee) {
|
||||
void layoutNEMTransferXEM(const char *desc, uint64_t quantity, const bignum256 *multiplier, uint64_t fee) {
|
||||
char str_out[32], str_fee[32];
|
||||
bignum256 amnt;
|
||||
|
||||
nemFormatAmount(&amnt, quantity, NEM_XEM_DIVISIBILITY, mul, " " NEM_XEM_TICKER, str_out, sizeof(str_out));
|
||||
nem_mosaicFormatAmount(NEM_MOSAIC_DEFINITION_XEM, quantity, multiplier, str_out, sizeof(str_out));
|
||||
nem_mosaicFormatAmount(NEM_MOSAIC_DEFINITION_XEM, fee, NULL, str_fee, sizeof(str_fee));
|
||||
|
||||
bn_read_uint64(fee, &amnt);
|
||||
bn_format(&amnt, NULL, " " NEM_XEM_TICKER, NEM_XEM_DIVISIBILITY, str_fee, sizeof(str_fee));
|
||||
layoutDialogSwipe(&bmp_icon_question,
|
||||
_("Cancel"),
|
||||
_("Next"),
|
||||
@ -522,14 +509,11 @@ void layoutNEMTransferXEM(const char *desc, uint64_t quantity, const bignum256 *
|
||||
|
||||
void layoutNEMNetworkFee(const char *desc, bool confirm, const char *fee1_desc, uint64_t fee1, const char *fee2_desc, uint64_t fee2) {
|
||||
char str_fee1[32], str_fee2[32];
|
||||
bignum256 amnt;
|
||||
|
||||
bn_read_uint64(fee1, &amnt);
|
||||
bn_format(&amnt, NULL, " " NEM_XEM_TICKER, NEM_XEM_DIVISIBILITY, str_fee1, sizeof(str_fee1));
|
||||
nem_mosaicFormatAmount(NEM_MOSAIC_DEFINITION_XEM, fee1, NULL, str_fee1, sizeof(str_fee1));
|
||||
|
||||
if (fee2_desc) {
|
||||
bn_read_uint64(fee2, &amnt);
|
||||
bn_format(&amnt, NULL, " " NEM_XEM_TICKER, NEM_XEM_DIVISIBILITY, str_fee2, sizeof(str_fee2));
|
||||
nem_mosaicFormatAmount(NEM_MOSAIC_DEFINITION_XEM, fee2, NULL, str_fee2, sizeof(str_fee2));
|
||||
}
|
||||
|
||||
layoutDialogSwipe(&bmp_icon_question,
|
||||
@ -544,15 +528,35 @@ void layoutNEMNetworkFee(const char *desc, bool confirm, const char *fee1_desc,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void layoutNEMTransferMosaic(const char *namespace, const char *mosaic, uint64_t quantity, const bignum256 *mul) {
|
||||
void layoutNEMTransferMosaic(const NEMMosaicDefinition *definition, uint64_t quantity, const bignum256 *multiplier) {
|
||||
char str_out[32], str_levy[32];
|
||||
|
||||
nem_mosaicFormatAmount(definition, quantity, multiplier, str_out, sizeof(str_out));
|
||||
|
||||
if (definition->has_levy) {
|
||||
nem_mosaicFormatLevy(definition, quantity, multiplier, str_levy, sizeof(str_levy));
|
||||
}
|
||||
|
||||
layoutDialogSwipe(&bmp_icon_question,
|
||||
_("Cancel"),
|
||||
_("Next"),
|
||||
definition->has_name ? definition->name : _("Mosaic"),
|
||||
_("Confirm transfer of"),
|
||||
str_out,
|
||||
definition->has_levy ? _("and levy of") : NULL,
|
||||
definition->has_levy ? str_levy : NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void layoutNEMTransferUnknownMosaic(const char *namespace, const char *mosaic, uint64_t quantity, const bignum256 *multiplier) {
|
||||
char mosaic_name[256];
|
||||
strlcpy(mosaic_name, namespace, sizeof(mosaic_name));
|
||||
strlcat(mosaic_name, ".", sizeof(mosaic_name));
|
||||
strlcat(mosaic_name, mosaic, sizeof(mosaic_name));
|
||||
|
||||
char str_out[32];
|
||||
bignum256 amnt;
|
||||
nemFormatAmount(&amnt, quantity, 0, mul, NULL, str_out, sizeof(str_out));
|
||||
nem_mosaicFormatAmount(NULL, quantity, multiplier, str_out, sizeof(str_out));
|
||||
|
||||
char *decimal = strchr(str_out, '.');
|
||||
if (decimal != NULL) {
|
||||
@ -587,24 +591,3 @@ void layoutNEMTransferPayload(const uint8_t *payload, size_t length, bool encryp
|
||||
str[0], str[1], str[2], str[3], NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void layoutNEMTransferTo(const char *desc, const char *address) {
|
||||
static char first_third[NEM_ADDRESS_SIZE / 3 + 1];
|
||||
strlcpy(first_third, address, sizeof(first_third));
|
||||
|
||||
static char second_third[NEM_ADDRESS_SIZE / 3 + 1];
|
||||
strlcpy(second_third, &address[NEM_ADDRESS_SIZE / 3], sizeof(second_third));
|
||||
|
||||
const char *third_third = &address[NEM_ADDRESS_SIZE * 2 / 3];
|
||||
|
||||
layoutDialogSwipe(&bmp_icon_question,
|
||||
_("Cancel"),
|
||||
_("Confirm"),
|
||||
desc,
|
||||
_("Confirm transfer to"),
|
||||
first_third,
|
||||
second_third,
|
||||
third_third,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
@ -47,10 +47,12 @@ void layoutPublicKey(const uint8_t *pubkey);
|
||||
void layoutSignIdentity(const IdentityType *identity, const char *challenge);
|
||||
void layoutDecryptIdentity(const IdentityType *identity);
|
||||
void layoutU2FDialog(const char *verb, const char *appname, const BITMAP *appicon);
|
||||
void layoutNEMDialog(const BITMAP *icon, const char *btnNo, const char *btnYes, const char *desc, const char *line1, const char *address, const char *line5, const char *line6);
|
||||
void layoutNEMTransferXEM(const char *desc, uint64_t quantity, const bignum256 *mul, uint64_t fee);
|
||||
|
||||
void layoutNEMDialog(const BITMAP *icon, const char *btnNo, const char *btnYes, const char *desc, const char *line1, const char *address);
|
||||
void layoutNEMTransferXEM(const char *desc, uint64_t quantity, const bignum256 *multiplier, uint64_t fee);
|
||||
void layoutNEMNetworkFee(const char *desc, bool confirm, const char *fee1_desc, uint64_t fee1, const char *fee2_desc, uint64_t fee2);
|
||||
void layoutNEMTransferMosaic(const char *namespace, const char *mosaic, uint64_t quantity, const bignum256 *mul);
|
||||
void layoutNEMTransferMosaic(const NEMMosaicDefinition *definition, uint64_t quantity, const bignum256 *multiplier);
|
||||
void layoutNEMTransferUnknownMosaic(const char *namespace, const char *mosaic, uint64_t quantity, const bignum256 *multiplier);
|
||||
void layoutNEMTransferPayload(const uint8_t *payload, size_t length, bool encrypted);
|
||||
|
||||
#endif
|
||||
|
147
firmware/nem2.c
147
firmware/nem2.c
@ -25,6 +25,9 @@
|
||||
#include "layout2.h"
|
||||
#include "protect.h"
|
||||
#include "rng.h"
|
||||
#include "secp256k1.h"
|
||||
|
||||
static void format_amount(const NEMMosaicDefinition *definition, uint64_t quantity, const bignum256 *multiplier, const bignum256 *multiplier2, int divisor, char *str_out, size_t size);
|
||||
|
||||
const char *nem_validate_common(NEMTransactionCommon *common, bool inner) {
|
||||
if (!common->has_network) {
|
||||
@ -92,51 +95,61 @@ const char *nem_validate_provision_namespace(const NEMProvisionNamespace *provis
|
||||
|
||||
bool nem_askTransfer(const NEMTransactionCommon *common, const NEMTransfer *transfer, const char *desc) {
|
||||
if (transfer->mosaics_count) {
|
||||
bool done[transfer->mosaics_count];
|
||||
memset(done, 0, sizeof(done));
|
||||
struct {
|
||||
bool skip;
|
||||
uint64_t quantity;
|
||||
const NEMMosaicDefinition *definition;
|
||||
} mosaics[transfer->mosaics_count], *xem = NULL;
|
||||
|
||||
uint64_t quantity[transfer->mosaics_count];
|
||||
uint64_t *xemQuantity = NULL;
|
||||
|
||||
bignum256 mul;
|
||||
bn_read_uint64(transfer->amount, &mul);
|
||||
memset(mosaics, 0, sizeof(mosaics));
|
||||
|
||||
for (size_t i = 0; i < transfer->mosaics_count; i++) {
|
||||
// Skip duplicate mosaics
|
||||
if (done[i]) continue;
|
||||
if (mosaics[i].skip) continue;
|
||||
|
||||
const NEMMosaic *mosaic = &transfer->mosaics[i];
|
||||
|
||||
// XEM is treated specially
|
||||
if (strcmp(mosaic->namespace, "nem") == 0 && strcmp(mosaic->mosaic, "xem") == 0) {
|
||||
done[i] = true;
|
||||
xemQuantity = &quantity[i];
|
||||
// XEM is displayed separately
|
||||
if ((mosaics[i].definition = nem_mosaicByName(mosaic->namespace, mosaic->mosaic))) {
|
||||
if (mosaics[i].definition == NEM_MOSAIC_DEFINITION_XEM) {
|
||||
// Do not display as a mosaic
|
||||
mosaics[i].skip = true;
|
||||
xem = &mosaics[i];
|
||||
}
|
||||
}
|
||||
|
||||
quantity[i] = mosaic->quantity;
|
||||
mosaics[i].quantity = mosaic->quantity;
|
||||
for (size_t j = i + 1; j < transfer->mosaics_count; j++) {
|
||||
const NEMMosaic *new_mosaic = &transfer->mosaics[j];
|
||||
|
||||
if (strcmp(mosaic->namespace, new_mosaic->namespace) == 0 && strcmp(mosaic->mosaic, new_mosaic->mosaic) == 0) {
|
||||
// Duplicate mosaics are merged into one
|
||||
done[i] = true;
|
||||
quantity[i] += transfer->mosaics[j].quantity;
|
||||
if (nem_mosaicMatches(mosaics[i].definition, new_mosaic->namespace, new_mosaic->mosaic)) {
|
||||
// Merge duplicate mosaics
|
||||
mosaics[j].skip = true;
|
||||
mosaics[i].quantity += new_mosaic->quantity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layoutNEMTransferXEM(desc, xemQuantity == NULL ? 0 : *xemQuantity, &mul, common->fee);
|
||||
bignum256 multiplier;
|
||||
bn_read_uint64(transfer->amount, &multiplier);
|
||||
|
||||
layoutNEMTransferXEM(desc, xem ? xem->quantity : 0, &multiplier, common->fee);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < transfer->mosaics_count; i++) {
|
||||
// Skip special or duplicate mosaics
|
||||
if (done[i]) continue;
|
||||
// Skip duplicate mosaics or XEM
|
||||
if (mosaics[i].skip) continue;
|
||||
|
||||
const NEMMosaic *mosaic = &transfer->mosaics[i];
|
||||
|
||||
layoutNEMTransferMosaic(mosaic->namespace, mosaic->mosaic, quantity[i], &mul);
|
||||
if (mosaics[i].definition) {
|
||||
layoutNEMTransferMosaic(mosaics[i].definition, mosaics[i].quantity, &multiplier);
|
||||
} else {
|
||||
layoutNEMTransferUnknownMosaic(mosaic->namespace, mosaic->mosaic, mosaics[i].quantity, &multiplier);
|
||||
}
|
||||
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return false;
|
||||
}
|
||||
@ -160,9 +173,7 @@ bool nem_askTransfer(const NEMTransactionCommon *common, const NEMTransfer *tran
|
||||
_("Confirm"),
|
||||
desc,
|
||||
_("Confirm transfer to"),
|
||||
transfer->recipient,
|
||||
NULL,
|
||||
NULL);
|
||||
transfer->recipient);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) {
|
||||
return false;
|
||||
}
|
||||
@ -285,16 +296,12 @@ bool nem_askMultisig(const char *address, const char *desc, bool cosigning, uint
|
||||
_("Next"),
|
||||
desc,
|
||||
cosigning ? _("Cosign transaction for") : _("Initiate transaction for"),
|
||||
address,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
address);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
layoutNEMNetworkFee(desc, false, _("Confirm multisig fee"), fee, NULL, 0);
|
||||
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return false;
|
||||
}
|
||||
@ -329,3 +336,85 @@ bool nem_fsmMultisig(nem_transaction_ctx *context, const NEMTransactionCommon *c
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const NEMMosaicDefinition *nem_mosaicByName(const char *namespace, const char *mosaic) {
|
||||
for (size_t i = 0; i < NEM_MOSAIC_DEFINITIONS_COUNT; i++) {
|
||||
const NEMMosaicDefinition *definition = &NEM_MOSAIC_DEFINITIONS[i];
|
||||
|
||||
if (nem_mosaicMatches(definition, namespace, mosaic)) {
|
||||
return definition;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void format_amount(const NEMMosaicDefinition *definition, uint64_t quantity, const bignum256 *multiplier, const bignum256 *multiplier2, int divisor, char *str_out, size_t size) {
|
||||
uint32_t divisibility = definition && definition->has_divisibility ? definition->divisibility : 0;
|
||||
const char *ticker = definition && definition->has_ticker ? definition->ticker : NULL;
|
||||
|
||||
bignum256 amnt;
|
||||
bn_read_uint64(quantity, &amnt);
|
||||
|
||||
if (multiplier2) {
|
||||
bn_multiply(multiplier2, &amnt, &secp256k1.prime);
|
||||
}
|
||||
|
||||
// Do not use prefix/suffix with bn_format, it messes with the truncation code
|
||||
if (multiplier) {
|
||||
bn_multiply(multiplier, &amnt, &secp256k1.prime);
|
||||
divisor += NEM_MOSAIC_DEFINITION_XEM->divisibility;
|
||||
}
|
||||
|
||||
// bn_format(amnt / (10 ^ divisor), divisibility)
|
||||
bn_format(&amnt, NULL, NULL, divisibility + divisor, str_out, size);
|
||||
|
||||
// Truncate as if we called bn_format with (divisibility) instead of (divisibility + divisor)
|
||||
char *decimal = strchr(str_out, '.');
|
||||
if (decimal != NULL) {
|
||||
const char *terminator = strchr(str_out, '\0');
|
||||
|
||||
if (divisibility == 0) {
|
||||
// Truncate as an integer
|
||||
*decimal = '\0';
|
||||
} else {
|
||||
char *end = decimal + divisibility + 1;
|
||||
if (end < terminator) {
|
||||
*end = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ticker) {
|
||||
strlcat(str_out, " ", size);
|
||||
strlcat(str_out, ticker, size);
|
||||
}
|
||||
}
|
||||
|
||||
void nem_mosaicFormatAmount(const NEMMosaicDefinition *definition, uint64_t quantity, const bignum256 *multiplier, char *str_out, size_t size) {
|
||||
format_amount(definition, quantity, multiplier, NULL, 0, str_out, size);
|
||||
}
|
||||
|
||||
bool nem_mosaicFormatLevy(const NEMMosaicDefinition *definition, uint64_t quantity, const bignum256 *multiplier, char *str_out, size_t size) {
|
||||
bignum256 multiplier2;
|
||||
|
||||
if (!definition->has_levy || !definition->has_fee) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (definition->levy) {
|
||||
case NEMMosaicLevy_MosaicLevy_Absolute:
|
||||
format_amount(definition, definition->fee, NULL, NULL, 0, str_out, size);
|
||||
break;
|
||||
|
||||
case NEMMosaicLevy_MosaicLevy_Percentile:
|
||||
bn_read_uint64(definition->fee, &multiplier2);
|
||||
format_amount(definition, quantity, multiplier, &multiplier2, NEM_LEVY_PERCENTILE_DIVISOR, str_out, size);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define __NEM2_H__
|
||||
|
||||
#include "nem.h"
|
||||
#include "nem_mosaics.h"
|
||||
|
||||
#include "messages.pb.h"
|
||||
#include "types.pb.h"
|
||||
@ -43,4 +44,12 @@ bool nem_fsmProvisionNamespace(nem_transaction_ctx *context, const NEMTransactio
|
||||
bool nem_askMultisig(const char *address, const char *desc, bool cosigning, uint64_t fee);
|
||||
bool nem_fsmMultisig(nem_transaction_ctx *context, const NEMTransactionCommon *common, const nem_transaction_ctx *inner, bool cosigning);
|
||||
|
||||
const NEMMosaicDefinition *nem_mosaicByName(const char *namespace, const char *mosaic);
|
||||
void nem_mosaicFormatAmount(const NEMMosaicDefinition *definition, uint64_t quantity, const bignum256 *multiplier, char *str_out, size_t size);
|
||||
bool nem_mosaicFormatLevy(const NEMMosaicDefinition *definition, uint64_t quantity, const bignum256 *multiplier, char *str_out, size_t size);
|
||||
|
||||
static inline bool nem_mosaicMatches(const NEMMosaicDefinition *definition, const char *namespace, const char *mosaic) {
|
||||
return strcmp(namespace, definition->namespace) == 0 && strcmp(mosaic, definition->mosaic) == 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
16
firmware/nem_mosaics.c
Normal file
16
firmware/nem_mosaics.c
Normal file
@ -0,0 +1,16 @@
|
||||
// This file is automatically generated by nem_mosaics.py -- DO NOT EDIT!
|
||||
|
||||
#include "nem_mosaics.h"
|
||||
|
||||
const NEMMosaicDefinition NEM_MOSAIC_DEFINITIONS[NEM_MOSAIC_DEFINITIONS_COUNT] = {{
|
||||
.has_ticker = true,
|
||||
.ticker = " XEM",
|
||||
.has_namespace = true,
|
||||
.namespace = "nem",
|
||||
.has_mosaic = true,
|
||||
.mosaic = "xem",
|
||||
.has_divisibility = true,
|
||||
.divisibility = 6,
|
||||
}};
|
||||
|
||||
const NEMMosaicDefinition *NEM_MOSAIC_DEFINITION_XEM = NEM_MOSAIC_DEFINITIONS;
|
13
firmware/nem_mosaics.h
Normal file
13
firmware/nem_mosaics.h
Normal file
@ -0,0 +1,13 @@
|
||||
// This file is automatically generated by nem_mosaics.py -- DO NOT EDIT!
|
||||
|
||||
#ifndef __NEM_MOSAICS_H__
|
||||
#define __NEM_MOSAICS_H__
|
||||
|
||||
#include "types.pb.h"
|
||||
|
||||
#define NEM_MOSAIC_DEFINITIONS_COUNT (1)
|
||||
|
||||
extern const NEMMosaicDefinition NEM_MOSAIC_DEFINITIONS[NEM_MOSAIC_DEFINITIONS_COUNT];
|
||||
extern const NEMMosaicDefinition *NEM_MOSAIC_DEFINITION_XEM;
|
||||
|
||||
#endif
|
8
firmware/nem_mosaics.json
Normal file
8
firmware/nem_mosaics.json
Normal file
@ -0,0 +1,8 @@
|
||||
[
|
||||
{
|
||||
"ticker": " XEM",
|
||||
"namespace": "nem",
|
||||
"mosaic": "xem",
|
||||
"divisibility": 6
|
||||
}
|
||||
]
|
95
firmware/nem_mosaics.py
Executable file
95
firmware/nem_mosaics.py
Executable file
@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env python3
|
||||
import json, os
|
||||
from google.protobuf import json_format
|
||||
from itertools import chain
|
||||
import protob.types_pb2 as types
|
||||
|
||||
HEADER_TEMPLATE = """
|
||||
// This file is automatically generated by nem_mosaics.py -- DO NOT EDIT!
|
||||
|
||||
#ifndef __NEM_MOSAICS_H__
|
||||
#define __NEM_MOSAICS_H__
|
||||
|
||||
#include "types.pb.h"
|
||||
|
||||
#define NEM_MOSAIC_DEFINITIONS_COUNT ({count})
|
||||
|
||||
extern const NEMMosaicDefinition NEM_MOSAIC_DEFINITIONS[NEM_MOSAIC_DEFINITIONS_COUNT];
|
||||
extern const NEMMosaicDefinition *NEM_MOSAIC_DEFINITION_XEM;
|
||||
|
||||
#endif
|
||||
""".lstrip()
|
||||
|
||||
CODE_TEMPLATE = """
|
||||
// This file is automatically generated by nem_mosaics.py -- DO NOT EDIT!
|
||||
|
||||
#include "nem_mosaics.h"
|
||||
|
||||
const NEMMosaicDefinition NEM_MOSAIC_DEFINITIONS[NEM_MOSAIC_DEFINITIONS_COUNT] = {code};
|
||||
|
||||
const NEMMosaicDefinition *NEM_MOSAIC_DEFINITION_XEM = NEM_MOSAIC_DEFINITIONS;
|
||||
""".lstrip()
|
||||
|
||||
def format_primitive(value):
|
||||
if type(value) is bool:
|
||||
return ("false", "true")[value]
|
||||
elif type(value) in (int, float):
|
||||
return str(value)
|
||||
elif type(value) is str:
|
||||
return json.dumps(value)
|
||||
elif type(value) is list:
|
||||
return "{ " + ", ".join(
|
||||
format_primitive(item) for item in value
|
||||
) + " }"
|
||||
else:
|
||||
raise TypeError
|
||||
|
||||
def format_struct(struct):
|
||||
return "{\n" + "\n".join(
|
||||
"\t.{0} = {1},".format(member, value) for member, value in struct.items()
|
||||
) + "\n}"
|
||||
|
||||
|
||||
def format_field(field, value):
|
||||
if field.message_type is not None:
|
||||
raise TypeError
|
||||
elif field.enum_type:
|
||||
return "{0}_{1}".format(field.enum_type.name, field.enum_type.values_by_number[value].name)
|
||||
elif hasattr(value, "_values"):
|
||||
return format_primitive(value._values)
|
||||
else:
|
||||
return format_primitive(value)
|
||||
|
||||
def field_to_meta(field, value):
|
||||
if hasattr(value, "_values"):
|
||||
return ("{}_count".format(field.name), format_primitive(len(value._values)))
|
||||
else:
|
||||
return ("has_{}".format(field.name), format_primitive(True))
|
||||
|
||||
def message_to_struct(_message, proto):
|
||||
message = json_format.ParseDict(_message, proto())
|
||||
return dict(chain.from_iterable(
|
||||
(
|
||||
field_to_meta(field, value),
|
||||
(field.name, format_field(field, value)),
|
||||
) for field, value in message.ListFields()
|
||||
))
|
||||
|
||||
def format_message(message, proto):
|
||||
return format_struct(message_to_struct(message, proto))
|
||||
|
||||
def format_messages(messages, proto):
|
||||
return "{" + ",\n".join(
|
||||
format_message(message, proto) for message in messages
|
||||
) + "}"
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.chdir(os.path.abspath(os.path.dirname(__file__)))
|
||||
|
||||
messages = json.load(open("nem_mosaics.json"))
|
||||
|
||||
with open("nem_mosaics.h", "w+") as f:
|
||||
f.write(HEADER_TEMPLATE.format(count=format_primitive(len(messages))))
|
||||
|
||||
with open("nem_mosaics.c", "w+") as f:
|
||||
f.write(CODE_TEMPLATE.format(code=format_messages(messages, types.NEMMosaicDefinition)))
|
Loading…
Reference in New Issue
Block a user