mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-23 06:48:16 +00:00
nem2: Handle Mosaic Definition Creation transactions
This commit is contained in:
parent
b0394622a3
commit
17e33d5517
@ -1154,13 +1154,14 @@ void fsm_msgNEMSignTx(NEMSignTx *msg) {
|
||||
CHECK_PARAM(msg->has_transaction, _("No common provided"));
|
||||
|
||||
// Ensure exactly one transaction is provided
|
||||
unsigned int provided = msg->has_transfer + msg->has_provision_namespace;
|
||||
unsigned int provided = msg->has_transfer + msg->has_provision_namespace + msg->has_mosaic_creation;
|
||||
CHECK_PARAM(provided != 0, _("No transaction provided"));
|
||||
CHECK_PARAM(provided == 1, _("More than one transaction provided"));
|
||||
|
||||
NEM_CHECK_PARAM(nem_validate_common(&msg->transaction, false));
|
||||
NEM_CHECK_PARAM_WHEN(msg->has_transfer, nem_validate_transfer(&msg->transfer, msg->transaction.network));
|
||||
NEM_CHECK_PARAM_WHEN(msg->has_provision_namespace, nem_validate_provision_namespace(&msg->provision_namespace, msg->transaction.network));
|
||||
NEM_CHECK_PARAM_WHEN(msg->has_mosaic_creation, nem_validate_mosaic_creation(&msg->mosaic_creation, msg->transaction.network));
|
||||
|
||||
bool cosigning = msg->has_cosigning && msg->cosigning;
|
||||
if (msg->has_multisig) {
|
||||
@ -1187,8 +1188,18 @@ void fsm_msgNEMSignTx(NEMSignTx *msg) {
|
||||
}
|
||||
}
|
||||
|
||||
RESP_INIT(NEMSignedTx);
|
||||
|
||||
HDNode *node = fsm_getDerivedNode(ED25519_KECCAK_NAME, msg->transaction.address_n, msg->transaction.address_n_count);
|
||||
if (!node) return;
|
||||
|
||||
hdnode_fill_public_key(node);
|
||||
|
||||
const NEMTransactionCommon *common = msg->has_multisig ? &msg->multisig : &msg->transaction;
|
||||
|
||||
char address[NEM_ADDRESS_SIZE + 1];
|
||||
hdnode_get_nem_address(node, common->network, address);
|
||||
|
||||
if (msg->has_transfer && !nem_askTransfer(common, &msg->transfer, network)) {
|
||||
fsm_sendFailure(FailureType_Failure_ActionCancelled, _("Signing cancelled by user"));
|
||||
layoutHome();
|
||||
@ -1201,12 +1212,11 @@ void fsm_msgNEMSignTx(NEMSignTx *msg) {
|
||||
return;
|
||||
}
|
||||
|
||||
RESP_INIT(NEMSignedTx);
|
||||
|
||||
HDNode *node = fsm_getDerivedNode(ED25519_KECCAK_NAME, msg->transaction.address_n, msg->transaction.address_n_count);
|
||||
if (!node) return;
|
||||
|
||||
hdnode_fill_public_key(node);
|
||||
if (msg->has_mosaic_creation && !nem_askMosaicCreation(common, &msg->mosaic_creation, network, address)) {
|
||||
fsm_sendFailure(FailureType_Failure_ActionCancelled, _("Signing cancelled by user"));
|
||||
layoutHome();
|
||||
return;
|
||||
}
|
||||
|
||||
nem_transaction_ctx context;
|
||||
nem_transaction_start(&context, &node->public_key[1], resp->data.bytes, sizeof(resp->data.bytes));
|
||||
@ -1227,6 +1237,11 @@ void fsm_msgNEMSignTx(NEMSignTx *msg) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->has_mosaic_creation && !nem_fsmMosaicCreation(&inner, &msg->multisig, &msg->mosaic_creation)) {
|
||||
layoutHome();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nem_fsmMultisig(&context, &msg->transaction, &inner, cosigning)) {
|
||||
layoutHome();
|
||||
return;
|
||||
@ -1241,6 +1256,11 @@ void fsm_msgNEMSignTx(NEMSignTx *msg) {
|
||||
layoutHome();
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->has_mosaic_creation && !nem_fsmMosaicCreation(&context, &msg->transaction, &msg->mosaic_creation)) {
|
||||
layoutHome();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
resp->has_data = true;
|
||||
|
@ -550,10 +550,8 @@ void layoutNEMTransferMosaic(const NEMMosaicDefinition *definition, uint64_t qua
|
||||
}
|
||||
|
||||
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 mosaic_name[32];
|
||||
nem_mosaicFormatName(namespace, mosaic, mosaic_name, sizeof(mosaic_name));
|
||||
|
||||
char str_out[32];
|
||||
nem_mosaicFormatAmount(NULL, quantity, multiplier, str_out, sizeof(str_out));
|
||||
@ -591,3 +589,65 @@ void layoutNEMTransferPayload(const uint8_t *payload, size_t length, bool encryp
|
||||
str[0], str[1], str[2], str[3], NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void layoutNEMMosaicDescription(const char *description) {
|
||||
const char **str = split_message((uint8_t *) description, strlen(description), 16);
|
||||
layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Next"),
|
||||
_("Mosaic Description"),
|
||||
str[0], str[1], str[2], str[3], NULL, NULL);
|
||||
}
|
||||
|
||||
void layoutNEMLevy(const NEMMosaicDefinition *definition) {
|
||||
const NEMMosaicDefinition *mosaic;
|
||||
if (nem_mosaicMatches(definition, definition->levy_namespace, definition->levy_mosaic)) {
|
||||
mosaic = definition;
|
||||
} else {
|
||||
mosaic = nem_mosaicByName(definition->levy_namespace, definition->levy_mosaic);
|
||||
}
|
||||
|
||||
char mosaic_name[32];
|
||||
if (mosaic == NULL) {
|
||||
nem_mosaicFormatName(definition->levy_namespace, definition->levy_mosaic, mosaic_name, sizeof(mosaic_name));
|
||||
}
|
||||
|
||||
char str_out[32];
|
||||
bignum256 amnt;
|
||||
|
||||
switch (definition->levy) {
|
||||
case NEMMosaicLevy_MosaicLevy_Percentile:
|
||||
bn_read_uint64(definition->fee, &amnt);
|
||||
bn_format(&amnt, NULL, NULL, 0, str_out, sizeof(str_out));
|
||||
|
||||
char *decimal = strchr(str_out, '.');
|
||||
if (decimal != NULL) {
|
||||
*decimal = '\0';
|
||||
}
|
||||
|
||||
layoutDialogSwipe(&bmp_icon_question,
|
||||
_("Cancel"),
|
||||
_("Next"),
|
||||
_("Percentile Levy"),
|
||||
_("Raw levy value is"),
|
||||
str_out,
|
||||
_("in"),
|
||||
mosaic ? (mosaic == definition ? _("the same mosaic") : mosaic->name) : mosaic_name,
|
||||
NULL,
|
||||
NULL);
|
||||
break;
|
||||
|
||||
case NEMMosaicLevy_MosaicLevy_Absolute:
|
||||
default:
|
||||
nem_mosaicFormatAmount(mosaic, definition->fee, NULL, str_out, sizeof(str_out));
|
||||
layoutDialogSwipe(&bmp_icon_question,
|
||||
_("Cancel"),
|
||||
_("Next"),
|
||||
_("Absolute Levy"),
|
||||
_("Levy is"),
|
||||
str_out,
|
||||
mosaic ? (mosaic == definition ? _("in the same mosaic") : NULL) : _("in raw units of"),
|
||||
mosaic ? NULL : mosaic_name,
|
||||
NULL,
|
||||
NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -54,5 +54,7 @@ void layoutNEMNetworkFee(const char *desc, bool confirm, const char *fee1_desc,
|
||||
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 layoutNEMMosaicDescription(const char *description);
|
||||
void layoutNEMLevy(const NEMMosaicDefinition *definition);
|
||||
|
||||
#endif
|
||||
|
158
firmware/nem2.c
158
firmware/nem2.c
@ -93,6 +93,40 @@ const char *nem_validate_provision_namespace(const NEMProvisionNamespace *provis
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *nem_validate_mosaic_creation(const NEMMosaicCreation *mosaic_creation, uint8_t network) {
|
||||
if (!mosaic_creation->has_definition) return _("No mosaic definition provided");
|
||||
if (!mosaic_creation->has_sink) return _("No creation sink provided");
|
||||
if (!mosaic_creation->has_fee) return _("No creation sink fee provided");
|
||||
|
||||
if (!nem_validate_address(mosaic_creation->sink, network)) return _("Invalid creation sink address");
|
||||
|
||||
if (mosaic_creation->definition.has_name) return _("Name not allowed in mosaic creation transactions");
|
||||
if (mosaic_creation->definition.has_ticker) return _("Ticker not allowed in mosaic creation transactions");
|
||||
|
||||
if (!mosaic_creation->definition.has_namespace) return _("No mosaic namespace provided");
|
||||
if (!mosaic_creation->definition.has_mosaic) return _("No mosaic name provided");
|
||||
|
||||
if (mosaic_creation->definition.has_levy) {
|
||||
if (!mosaic_creation->definition.has_fee) return _("No levy address provided");
|
||||
if (!mosaic_creation->definition.has_levy_address) return _("No levy address provided");
|
||||
if (!mosaic_creation->definition.has_levy_namespace) return _("No levy namespace provided");
|
||||
if (!mosaic_creation->definition.has_levy_mosaic) return _("No levy mosaic name provided");
|
||||
|
||||
if (!mosaic_creation->definition.has_divisibility) return _("No divisibility provided");
|
||||
if (!mosaic_creation->definition.has_supply) return _("No supply provided");
|
||||
if (!mosaic_creation->definition.has_mutable_supply) return _("No supply mutability provided");
|
||||
if (!mosaic_creation->definition.has_transferable) return _("No mosaic transferability provided");
|
||||
if (!mosaic_creation->definition.has_description) return _("No description provided");
|
||||
|
||||
if (mosaic_creation->definition.divisibility > NEM_MAX_DIVISIBILITY) return _("Invalid divisibility provided");
|
||||
if (mosaic_creation->definition.supply > NEM_MAX_SUPPLY) return _("Invalid supply provided");
|
||||
|
||||
if (!nem_validate_address(mosaic_creation->definition.levy_address, network)) return _("Invalid levy address");
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool nem_askTransfer(const NEMTransactionCommon *common, const NEMTransfer *transfer, const char *desc) {
|
||||
if (transfer->mosaics_count) {
|
||||
struct {
|
||||
@ -310,6 +344,118 @@ bool nem_fsmProvisionNamespace(nem_transaction_ctx *context, const NEMTransactio
|
||||
provision_namespace->fee);
|
||||
}
|
||||
|
||||
bool nem_askMosaicCreation(const NEMTransactionCommon *common, const NEMMosaicCreation *mosaic_creation, const char *desc, const char *address) {
|
||||
layoutDialogSwipe(&bmp_icon_question,
|
||||
_("Cancel"),
|
||||
_("Next"),
|
||||
desc,
|
||||
_("Create mosaic"),
|
||||
mosaic_creation->definition.mosaic,
|
||||
_("under namespace"),
|
||||
mosaic_creation->definition.namespace,
|
||||
NULL,
|
||||
NULL);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
layoutNEMMosaicDescription(mosaic_creation->definition.description);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char str_out[32];
|
||||
bignum256 amnt;
|
||||
|
||||
bn_read_uint64(mosaic_creation->definition.supply, &amnt);
|
||||
bn_format(&amnt, NULL, NULL, 0, str_out, sizeof(str_out));
|
||||
|
||||
char *decimal = strchr(str_out, '.');
|
||||
if (decimal != NULL) {
|
||||
*decimal = '\0';
|
||||
}
|
||||
|
||||
strlcat(str_out, ".", sizeof(str_out));
|
||||
for (size_t i = 0; i < mosaic_creation->definition.divisibility; i++) {
|
||||
strlcat(str_out, "0", sizeof(str_out));
|
||||
}
|
||||
|
||||
layoutDialogSwipe(&bmp_icon_question,
|
||||
_("Cancel"),
|
||||
_("Next"),
|
||||
_("Properties"),
|
||||
mosaic_creation->definition.mutable_supply ? _("Mutable supply:") : _("Immutable supply:"),
|
||||
str_out,
|
||||
_("Mosaic will be"),
|
||||
mosaic_creation->definition.transferable ? _("transferable") : _("non-transferable"),
|
||||
NULL,
|
||||
NULL);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mosaic_creation->definition.has_levy) {
|
||||
layoutNEMLevy(&mosaic_creation->definition);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strcmp(address, mosaic_creation->definition.levy_address) == 0) {
|
||||
layoutDialogSwipe(&bmp_icon_question,
|
||||
_("Cancel"),
|
||||
_("Next"),
|
||||
_("Levy Recipient"),
|
||||
_("Levy will be paid to"),
|
||||
_("yourself"),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
} else {
|
||||
layoutNEMDialog(&bmp_icon_question,
|
||||
_("Cancel"),
|
||||
_("Next"),
|
||||
_("Levy Recipient"),
|
||||
_("Levy will be paid to"),
|
||||
mosaic_creation->definition.levy_address);
|
||||
}
|
||||
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
layoutNEMNetworkFee(desc, true, _("Confirm creation fee"), mosaic_creation->fee, _("and network fee of"), common->fee);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nem_fsmMosaicCreation(nem_transaction_ctx *context, const NEMTransactionCommon *common, const NEMMosaicCreation *mosaic_creation) {
|
||||
return nem_transaction_create_mosaic_creation(context,
|
||||
common->network,
|
||||
common->timestamp,
|
||||
NULL,
|
||||
common->fee,
|
||||
common->deadline,
|
||||
mosaic_creation->definition.namespace,
|
||||
mosaic_creation->definition.mosaic,
|
||||
mosaic_creation->definition.description,
|
||||
mosaic_creation->definition.divisibility,
|
||||
mosaic_creation->definition.supply,
|
||||
mosaic_creation->definition.mutable_supply,
|
||||
mosaic_creation->definition.transferable,
|
||||
mosaic_creation->definition.levy,
|
||||
mosaic_creation->definition.fee,
|
||||
mosaic_creation->definition.levy_address,
|
||||
mosaic_creation->definition.levy_namespace,
|
||||
mosaic_creation->definition.levy_mosaic,
|
||||
mosaic_creation->sink,
|
||||
mosaic_creation->fee);
|
||||
}
|
||||
|
||||
bool nem_askMultisig(const char *address, const char *desc, bool cosigning, uint64_t fee) {
|
||||
layoutNEMDialog(&bmp_icon_question,
|
||||
_("Cancel"),
|
||||
@ -422,14 +568,16 @@ bool nem_mosaicFormatLevy(const NEMMosaicDefinition *definition, uint64_t quanti
|
||||
return false;
|
||||
}
|
||||
|
||||
const NEMMosaicDefinition *levy_mosaic = nem_mosaicByName(definition->levy_namespace, definition->levy_mosaic);
|
||||
|
||||
switch (definition->levy) {
|
||||
case NEMMosaicLevy_MosaicLevy_Absolute:
|
||||
format_amount(definition, definition->fee, NULL, NULL, 0, str_out, size);
|
||||
format_amount(levy_mosaic, 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);
|
||||
format_amount(levy_mosaic, quantity, multiplier, &multiplier2, NEM_LEVY_PERCENTILE_DIVISOR, str_out, size);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -438,3 +586,9 @@ bool nem_mosaicFormatLevy(const NEMMosaicDefinition *definition, uint64_t quanti
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void nem_mosaicFormatName(const char *namespace, const char *mosaic, char *str_out, size_t size) {
|
||||
strlcpy(str_out, namespace, size);
|
||||
strlcat(str_out, ".", size);
|
||||
strlcat(str_out, mosaic, size);
|
||||
}
|
||||
|
@ -31,9 +31,7 @@
|
||||
const char *nem_validate_common(NEMTransactionCommon *common, bool inner);
|
||||
const char *nem_validate_transfer(const NEMTransfer *transfer, uint8_t network);
|
||||
const char *nem_validate_provision_namespace(const NEMProvisionNamespace *provision_namespace, uint8_t network);
|
||||
|
||||
bool nem_askTransaction(const char *desc, const NEMTransactionCommon *common, const NEMSignTx *msg);
|
||||
bool nem_fsmTransaction(nem_transaction_ctx *context, const HDNode *node, const NEMTransactionCommon *common, const NEMSignTx *msg);
|
||||
const char *nem_validate_mosaic_creation(const NEMMosaicCreation *mosaic_creation, uint8_t network);
|
||||
|
||||
bool nem_askTransfer(const NEMTransactionCommon *common, const NEMTransfer *transfer, const char *desc);
|
||||
bool nem_fsmTransfer(nem_transaction_ctx *context, const HDNode *node, const NEMTransactionCommon *common, const NEMTransfer *transfer);
|
||||
@ -41,12 +39,16 @@ bool nem_fsmTransfer(nem_transaction_ctx *context, const HDNode *node, const NEM
|
||||
bool nem_askProvisionNamespace(const NEMTransactionCommon *common, const NEMProvisionNamespace *provision_namespace, const char *desc);
|
||||
bool nem_fsmProvisionNamespace(nem_transaction_ctx *context, const NEMTransactionCommon *common, const NEMProvisionNamespace *provision_namespace);
|
||||
|
||||
bool nem_askMosaicCreation(const NEMTransactionCommon *common, const NEMMosaicCreation *mosaic_creation, const char *desc, const char *address);
|
||||
bool nem_fsmMosaicCreation(nem_transaction_ctx *context, const NEMTransactionCommon *common, const NEMMosaicCreation *mosaic_creation);
|
||||
|
||||
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);
|
||||
void nem_mosaicFormatName(const char *namespace, const char *mosaic, 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;
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include "nem_mosaics.h"
|
||||
|
||||
const NEMMosaicDefinition NEM_MOSAIC_DEFINITIONS[NEM_MOSAIC_DEFINITIONS_COUNT] = {{
|
||||
.has_name = true,
|
||||
.name = "XEM",
|
||||
.has_ticker = true,
|
||||
.ticker = " XEM",
|
||||
.has_namespace = true,
|
||||
@ -27,6 +29,10 @@ const NEMMosaicDefinition NEM_MOSAIC_DEFINITIONS[NEM_MOSAIC_DEFINITIONS_COUNT] =
|
||||
.levy = NEMMosaicLevy_MosaicLevy_Percentile,
|
||||
.has_fee = true,
|
||||
.fee = 10,
|
||||
.has_levy_namespace = true,
|
||||
.levy_namespace = "dim",
|
||||
.has_levy_mosaic = true,
|
||||
.levy_mosaic = "coin",
|
||||
},
|
||||
{
|
||||
.has_name = true,
|
||||
|
@ -1,5 +1,6 @@
|
||||
[
|
||||
{
|
||||
"name": "XEM",
|
||||
"ticker": " XEM",
|
||||
"namespace": "nem",
|
||||
"mosaic": "xem",
|
||||
@ -12,7 +13,9 @@
|
||||
"mosaic": "coin",
|
||||
"divisibility": 6,
|
||||
"levy": "MosaicLevy_Percentile",
|
||||
"fee": 10
|
||||
"fee": 10,
|
||||
"levy_namespace": "dim",
|
||||
"levy_mosaic": "coin"
|
||||
},
|
||||
{
|
||||
"name": "DIM TOKEN",
|
||||
|
Loading…
Reference in New Issue
Block a user