nem2: Handle Mosaic Definition Creation transactions

pull/25/head
Saleem Rashid 7 years ago
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

@ -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…
Cancel
Save