mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-22 23:48:12 +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.o
|
||||||
OBJS += ethereum_tokens.o
|
OBJS += ethereum_tokens.o
|
||||||
OBJS += nem2.o
|
OBJS += nem2.o
|
||||||
|
OBJS += nem_mosaics.o
|
||||||
|
|
||||||
OBJS += debug.o
|
OBJS += debug.o
|
||||||
|
|
||||||
|
@ -30,8 +30,8 @@
|
|||||||
#include "qr_encode.h"
|
#include "qr_encode.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "bignum.h"
|
#include "bignum.h"
|
||||||
#include "nem.h"
|
|
||||||
#include "secp256k1.h"
|
#include "secp256k1.h"
|
||||||
|
#include "nem2.h"
|
||||||
#include "gettext.h"
|
#include "gettext.h"
|
||||||
|
|
||||||
#define BITCOIN_DIVISIBILITY (8)
|
#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);
|
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) {
|
void layoutNEMDialog(const BITMAP *icon, const char *btnNo, const char *btnYes, const char *desc, const char *line1, const char *address) {
|
||||||
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) {
|
|
||||||
static char first_third[NEM_ADDRESS_SIZE / 3 + 1];
|
static char first_third[NEM_ADDRESS_SIZE / 3 + 1];
|
||||||
strlcpy(first_third, address, sizeof(first_third));
|
strlcpy(first_third, address, sizeof(first_third));
|
||||||
|
|
||||||
@ -496,18 +485,16 @@ void layoutNEMDialog(const BITMAP *icon, const char *btnNo, const char *btnYes,
|
|||||||
first_third,
|
first_third,
|
||||||
second_third,
|
second_third,
|
||||||
third_third,
|
third_third,
|
||||||
line5,
|
NULL,
|
||||||
line6);
|
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];
|
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,
|
layoutDialogSwipe(&bmp_icon_question,
|
||||||
_("Cancel"),
|
_("Cancel"),
|
||||||
_("Next"),
|
_("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) {
|
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];
|
char str_fee1[32], str_fee2[32];
|
||||||
bignum256 amnt;
|
|
||||||
|
|
||||||
bn_read_uint64(fee1, &amnt);
|
nem_mosaicFormatAmount(NEM_MOSAIC_DEFINITION_XEM, fee1, NULL, str_fee1, sizeof(str_fee1));
|
||||||
bn_format(&amnt, NULL, " " NEM_XEM_TICKER, NEM_XEM_DIVISIBILITY, str_fee1, sizeof(str_fee1));
|
|
||||||
|
|
||||||
if (fee2_desc) {
|
if (fee2_desc) {
|
||||||
bn_read_uint64(fee2, &amnt);
|
nem_mosaicFormatAmount(NEM_MOSAIC_DEFINITION_XEM, fee2, NULL, str_fee2, sizeof(str_fee2));
|
||||||
bn_format(&amnt, NULL, " " NEM_XEM_TICKER, NEM_XEM_DIVISIBILITY, str_fee2, sizeof(str_fee2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
layoutDialogSwipe(&bmp_icon_question,
|
layoutDialogSwipe(&bmp_icon_question,
|
||||||
@ -544,15 +528,35 @@ void layoutNEMNetworkFee(const char *desc, bool confirm, const char *fee1_desc,
|
|||||||
NULL);
|
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];
|
char mosaic_name[256];
|
||||||
strlcpy(mosaic_name, namespace, sizeof(mosaic_name));
|
strlcpy(mosaic_name, namespace, sizeof(mosaic_name));
|
||||||
strlcat(mosaic_name, ".", sizeof(mosaic_name));
|
strlcat(mosaic_name, ".", sizeof(mosaic_name));
|
||||||
strlcat(mosaic_name, mosaic, sizeof(mosaic_name));
|
strlcat(mosaic_name, mosaic, sizeof(mosaic_name));
|
||||||
|
|
||||||
char str_out[32];
|
char str_out[32];
|
||||||
bignum256 amnt;
|
nem_mosaicFormatAmount(NULL, quantity, multiplier, str_out, sizeof(str_out));
|
||||||
nemFormatAmount(&amnt, quantity, 0, mul, NULL, str_out, sizeof(str_out));
|
|
||||||
|
|
||||||
char *decimal = strchr(str_out, '.');
|
char *decimal = strchr(str_out, '.');
|
||||||
if (decimal != NULL) {
|
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);
|
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 layoutSignIdentity(const IdentityType *identity, const char *challenge);
|
||||||
void layoutDecryptIdentity(const IdentityType *identity);
|
void layoutDecryptIdentity(const IdentityType *identity);
|
||||||
void layoutU2FDialog(const char *verb, const char *appname, const BITMAP *appicon);
|
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 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);
|
void layoutNEMTransferPayload(const uint8_t *payload, size_t length, bool encrypted);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
147
firmware/nem2.c
147
firmware/nem2.c
@ -25,6 +25,9 @@
|
|||||||
#include "layout2.h"
|
#include "layout2.h"
|
||||||
#include "protect.h"
|
#include "protect.h"
|
||||||
#include "rng.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) {
|
const char *nem_validate_common(NEMTransactionCommon *common, bool inner) {
|
||||||
if (!common->has_network) {
|
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) {
|
bool nem_askTransfer(const NEMTransactionCommon *common, const NEMTransfer *transfer, const char *desc) {
|
||||||
if (transfer->mosaics_count) {
|
if (transfer->mosaics_count) {
|
||||||
bool done[transfer->mosaics_count];
|
struct {
|
||||||
memset(done, 0, sizeof(done));
|
bool skip;
|
||||||
|
uint64_t quantity;
|
||||||
|
const NEMMosaicDefinition *definition;
|
||||||
|
} mosaics[transfer->mosaics_count], *xem = NULL;
|
||||||
|
|
||||||
uint64_t quantity[transfer->mosaics_count];
|
memset(mosaics, 0, sizeof(mosaics));
|
||||||
uint64_t *xemQuantity = NULL;
|
|
||||||
|
|
||||||
bignum256 mul;
|
|
||||||
bn_read_uint64(transfer->amount, &mul);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < transfer->mosaics_count; i++) {
|
for (size_t i = 0; i < transfer->mosaics_count; i++) {
|
||||||
// Skip duplicate mosaics
|
// Skip duplicate mosaics
|
||||||
if (done[i]) continue;
|
if (mosaics[i].skip) continue;
|
||||||
|
|
||||||
const NEMMosaic *mosaic = &transfer->mosaics[i];
|
const NEMMosaic *mosaic = &transfer->mosaics[i];
|
||||||
|
|
||||||
// XEM is treated specially
|
// XEM is displayed separately
|
||||||
if (strcmp(mosaic->namespace, "nem") == 0 && strcmp(mosaic->mosaic, "xem") == 0) {
|
if ((mosaics[i].definition = nem_mosaicByName(mosaic->namespace, mosaic->mosaic))) {
|
||||||
done[i] = true;
|
if (mosaics[i].definition == NEM_MOSAIC_DEFINITION_XEM) {
|
||||||
xemQuantity = &quantity[i];
|
// 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++) {
|
for (size_t j = i + 1; j < transfer->mosaics_count; j++) {
|
||||||
const NEMMosaic *new_mosaic = &transfer->mosaics[j];
|
const NEMMosaic *new_mosaic = &transfer->mosaics[j];
|
||||||
|
|
||||||
if (strcmp(mosaic->namespace, new_mosaic->namespace) == 0 && strcmp(mosaic->mosaic, new_mosaic->mosaic) == 0) {
|
if (nem_mosaicMatches(mosaics[i].definition, new_mosaic->namespace, new_mosaic->mosaic)) {
|
||||||
// Duplicate mosaics are merged into one
|
// Merge duplicate mosaics
|
||||||
done[i] = true;
|
mosaics[j].skip = true;
|
||||||
quantity[i] += transfer->mosaics[j].quantity;
|
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)) {
|
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < transfer->mosaics_count; i++) {
|
for (size_t i = 0; i < transfer->mosaics_count; i++) {
|
||||||
// Skip special or duplicate mosaics
|
// Skip duplicate mosaics or XEM
|
||||||
if (done[i]) continue;
|
if (mosaics[i].skip) continue;
|
||||||
|
|
||||||
const NEMMosaic *mosaic = &transfer->mosaics[i];
|
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)) {
|
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -160,9 +173,7 @@ bool nem_askTransfer(const NEMTransactionCommon *common, const NEMTransfer *tran
|
|||||||
_("Confirm"),
|
_("Confirm"),
|
||||||
desc,
|
desc,
|
||||||
_("Confirm transfer to"),
|
_("Confirm transfer to"),
|
||||||
transfer->recipient,
|
transfer->recipient);
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) {
|
if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -285,16 +296,12 @@ bool nem_askMultisig(const char *address, const char *desc, bool cosigning, uint
|
|||||||
_("Next"),
|
_("Next"),
|
||||||
desc,
|
desc,
|
||||||
cosigning ? _("Cosign transaction for") : _("Initiate transaction for"),
|
cosigning ? _("Cosign transaction for") : _("Initiate transaction for"),
|
||||||
address,
|
address);
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
layoutNEMNetworkFee(desc, false, _("Confirm multisig fee"), fee, NULL, 0);
|
layoutNEMNetworkFee(desc, false, _("Confirm multisig fee"), fee, NULL, 0);
|
||||||
|
|
||||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -329,3 +336,85 @@ bool nem_fsmMultisig(nem_transaction_ctx *context, const NEMTransactionCommon *c
|
|||||||
|
|
||||||
return true;
|
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__
|
#define __NEM2_H__
|
||||||
|
|
||||||
#include "nem.h"
|
#include "nem.h"
|
||||||
|
#include "nem_mosaics.h"
|
||||||
|
|
||||||
#include "messages.pb.h"
|
#include "messages.pb.h"
|
||||||
#include "types.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_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);
|
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
|
#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