mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-22 22:38:08 +00:00
nem2: Handle multisig transactions
This commit is contained in:
parent
19033a459d
commit
563723a55f
@ -1149,14 +1149,39 @@ void fsm_msgNEMSignTx(NEMSignTx *msg) {
|
||||
CHECK_PARAM(msg->has_transaction, _("No common provided"));
|
||||
CHECK_PARAM(msg->has_transfer, _("No transaction provided"));
|
||||
|
||||
bool cosigning = msg->has_cosigning && msg->cosigning;
|
||||
|
||||
const char *reason;
|
||||
CHECK_PARAM(!(reason = nem_validate_common(&msg->transaction)), reason);
|
||||
CHECK_PARAM(!(reason = nem_validate_common(&msg->transaction, false)), reason);
|
||||
CHECK_PARAM(!(reason = nem_validate_transfer(&msg->transfer, msg->transaction.network)), reason);
|
||||
|
||||
if (msg->has_multisig) {
|
||||
CHECK_PARAM(!(reason = nem_validate_common(&msg->multisig, true)), reason);
|
||||
|
||||
CHECK_PARAM(msg->transaction.network == msg->multisig.network, _("Inner transaction network is different"));
|
||||
} else {
|
||||
CHECK_PARAM(!cosigning, _("No multisig transaction to cosign"));
|
||||
}
|
||||
|
||||
CHECK_INITIALIZED
|
||||
CHECK_PIN
|
||||
|
||||
if (!nem_askTransfer(&msg->transaction, &msg->transfer)) {
|
||||
const char *network = nem_network_name(msg->transaction.network);
|
||||
|
||||
if (msg->has_multisig) {
|
||||
char address[NEM_ADDRESS_SIZE + 1];
|
||||
nem_get_address(msg->multisig.signer.bytes, msg->multisig.network, address);
|
||||
|
||||
if (!nem_askMultisig(address, network, cosigning, msg->transaction.fee)) {
|
||||
fsm_sendFailure(FailureType_Failure_ActionCancelled, _("Signing cancelled by user"));
|
||||
layoutHome();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const NEMTransactionCommon *common = msg->has_multisig ? &msg->multisig : &msg->transaction;
|
||||
|
||||
if (msg->has_transfer && !nem_askTransfer(common, &msg->transfer, network)) {
|
||||
fsm_sendFailure(FailureType_Failure_ActionCancelled, _("Signing cancelled by user"));
|
||||
layoutHome();
|
||||
return;
|
||||
@ -1167,12 +1192,31 @@ void fsm_msgNEMSignTx(NEMSignTx *msg) {
|
||||
HDNode *node = fsm_getDerivedNode(ED25519_KECCAK_NAME, msg->transaction.address_n, msg->transaction.address_n_count);
|
||||
if (!node) return;
|
||||
|
||||
hdnode_fill_public_key(node);
|
||||
|
||||
nem_transaction_ctx context;
|
||||
nem_transaction_start(&context, &node->public_key[1], resp->data.bytes, sizeof(resp->data.bytes));
|
||||
|
||||
if (!nem_fsmTransfer(&context, node, &msg->transaction, &msg->transfer)) {
|
||||
layoutHome();
|
||||
return;
|
||||
if (msg->has_multisig) {
|
||||
uint8_t buffer[sizeof(resp->data.bytes)];
|
||||
|
||||
nem_transaction_ctx inner;
|
||||
nem_transaction_start(&inner, msg->multisig.signer.bytes, buffer, sizeof(buffer));
|
||||
|
||||
if (msg->has_transfer && !nem_fsmTransfer(&inner, NULL, &msg->multisig, &msg->transfer)) {
|
||||
layoutHome();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nem_fsmMultisig(&context, &msg->transaction, &inner, cosigning)) {
|
||||
layoutHome();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (msg->has_transfer && !nem_fsmTransfer(&context, node, &msg->transaction, &msg->transfer)) {
|
||||
layoutHome();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
resp->has_data = true;
|
||||
|
@ -479,6 +479,27 @@ static inline void nemFormatAmount(bignum256 *amnt, uint64_t quantity, int divis
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
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(icon,
|
||||
btnNo,
|
||||
btnYes,
|
||||
desc,
|
||||
line1,
|
||||
first_third,
|
||||
second_third,
|
||||
third_third,
|
||||
line5,
|
||||
line6);
|
||||
}
|
||||
|
||||
void layoutNEMTransferXEM(const char *desc, uint64_t quantity, const bignum256 *mul, uint64_t fee) {
|
||||
char str_out[32], str_fee[32];
|
||||
bignum256 amnt;
|
||||
@ -499,6 +520,30 @@ void layoutNEMTransferXEM(const char *desc, uint64_t quantity, const bignum256 *
|
||||
NULL);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
if (fee2_desc) {
|
||||
bn_read_uint64(fee2, &amnt);
|
||||
bn_format(&amnt, NULL, " " NEM_XEM_TICKER, NEM_XEM_DIVISIBILITY, str_fee2, sizeof(str_fee2));
|
||||
}
|
||||
|
||||
layoutDialogSwipe(&bmp_icon_question,
|
||||
_("Cancel"),
|
||||
confirm ? _("Confirm") : _("Next"),
|
||||
desc,
|
||||
fee1_desc,
|
||||
str_fee1,
|
||||
fee2_desc,
|
||||
fee2_desc ? str_fee2 : NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void layoutNEMTransferMosaic(const char *namespace, const char *mosaic, uint64_t quantity, const bignum256 *mul) {
|
||||
char mosaic_name[256];
|
||||
strlcpy(mosaic_name, namespace, sizeof(mosaic_name));
|
||||
|
@ -47,9 +47,10 @@ 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 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 layoutNEMTransferPayload(const uint8_t *payload, size_t length, bool encrypted);
|
||||
void layoutNEMTransferTo(const char *desc, const char *address);
|
||||
|
||||
#endif
|
||||
|
114
firmware/nem2.c
114
firmware/nem2.c
@ -26,16 +26,35 @@
|
||||
#include "protect.h"
|
||||
#include "rng.h"
|
||||
|
||||
const char *nem_validate_common(NEMTransactionCommon *common) {
|
||||
const char *nem_validate_common(NEMTransactionCommon *common, bool inner) {
|
||||
if (!common->has_network) {
|
||||
common->has_network = true;
|
||||
common->network = NEM_NETWORK_MAINNET;
|
||||
}
|
||||
|
||||
if (nem_network_name(common->network) == NULL) return _("Invalid NEM network");
|
||||
if (!common->has_timestamp) return _("No timestamp provided");
|
||||
if (!common->has_fee) return _("No fee provided");
|
||||
if (!common->has_deadline) return _("No deadline provided");
|
||||
if (nem_network_name(common->network) == NULL) {
|
||||
return inner ? _("Invalid NEM network in inner transaction") : _("Invalid NEM network");
|
||||
}
|
||||
|
||||
if (!common->has_timestamp) {
|
||||
return inner ? _("No timestamp provided in inner transaction") : _("No timestamp provided");
|
||||
}
|
||||
|
||||
if (!common->has_fee) {
|
||||
return inner ? _("No fee provided in inner transaction") : _("No fee provided");
|
||||
}
|
||||
|
||||
if (!common->has_deadline) {
|
||||
return inner ? _("No deadline provided in inner transaction") : _("No deadline provided");
|
||||
}
|
||||
|
||||
if (inner != common->has_signer) {
|
||||
return inner ? _("No signer provided in inner transaction") : _("Signer not allowed in outer transaction");
|
||||
}
|
||||
|
||||
if (common->has_signer && common->signer.size != sizeof(ed25519_public_key)) {
|
||||
return _("Invalid signer public key in inner transaction");
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -43,29 +62,26 @@ const char *nem_validate_common(NEMTransactionCommon *common) {
|
||||
const char *nem_validate_transfer(const NEMTransfer *transfer, uint8_t network) {
|
||||
if (!transfer->has_recipient) return _("No recipient provided");
|
||||
if (!transfer->has_amount) return _("No amount provided");
|
||||
if (transfer->has_public_key && transfer->public_key.size != 32) return _("Invalid recipient public key");
|
||||
|
||||
if (transfer->has_public_key && transfer->public_key.size != sizeof(ed25519_public_key)) {
|
||||
return _("Invalid recipient public key");
|
||||
}
|
||||
|
||||
if (!nem_validate_address(transfer->recipient, network)) return _("Invalid recipient address");
|
||||
|
||||
for (size_t i = 0; i < transfer->mosaics_count; i++) {
|
||||
const NEMMosaic *mosaic = &transfer->mosaics[i];
|
||||
|
||||
if (!mosaic->has_namespace) return "No mosaic namespace provided";
|
||||
if (!mosaic->has_mosaic) return "No mosaic name provided";
|
||||
if (!mosaic->has_quantity) return "No mosaic quantity provided";
|
||||
if (!mosaic->has_namespace) return _("No mosaic namespace provided");
|
||||
if (!mosaic->has_mosaic) return _("No mosaic name provided");
|
||||
if (!mosaic->has_quantity) return _("No mosaic quantity provided");
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool nem_askTransfer(const NEMTransactionCommon *common, const NEMTransfer *transfer) {
|
||||
const char *network = nem_network_name(common->network);
|
||||
if (network == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
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));
|
||||
@ -100,7 +116,7 @@ bool nem_askTransfer(const NEMTransactionCommon *common, const NEMTransfer *tran
|
||||
}
|
||||
}
|
||||
|
||||
layoutNEMTransferXEM(network, xemQuantity == NULL ? 0 : *xemQuantity, &mul, common->fee);
|
||||
layoutNEMTransferXEM(desc, xemQuantity == NULL ? 0 : *xemQuantity, &mul, common->fee);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return false;
|
||||
}
|
||||
@ -117,7 +133,7 @@ bool nem_askTransfer(const NEMTransactionCommon *common, const NEMTransfer *tran
|
||||
}
|
||||
}
|
||||
} else {
|
||||
layoutNEMTransferXEM(network, transfer->amount, NULL, common->fee);
|
||||
layoutNEMTransferXEM(desc, transfer->amount, NULL, common->fee);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) {
|
||||
return false;
|
||||
}
|
||||
@ -130,7 +146,14 @@ bool nem_askTransfer(const NEMTransactionCommon *common, const NEMTransfer *tran
|
||||
}
|
||||
}
|
||||
|
||||
layoutNEMTransferTo(network, transfer->recipient);
|
||||
layoutNEMDialog(&bmp_icon_question,
|
||||
_("Cancel"),
|
||||
_("Confirm"),
|
||||
desc,
|
||||
_("Confirm transfer to"),
|
||||
transfer->recipient,
|
||||
NULL,
|
||||
NULL);
|
||||
if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) {
|
||||
return false;
|
||||
}
|
||||
@ -203,10 +226,61 @@ bool nem_fsmTransfer(nem_transaction_ctx *context, const HDNode *node, const NEM
|
||||
mosaic->quantity);
|
||||
|
||||
if (!ret) {
|
||||
fsm_sendFailure(FailureType_Failure_ProcessError, "Failed to attach mosaics");
|
||||
fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to attach mosaics"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nem_askMultisig(const char *address, const char *desc, bool cosigning, uint64_t fee) {
|
||||
layoutNEMDialog(&bmp_icon_question,
|
||||
_("Cancel"),
|
||||
_("Next"),
|
||||
desc,
|
||||
cosigning ? _("Cosign transaction for") : _("Initiate transaction for"),
|
||||
address,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nem_fsmMultisig(nem_transaction_ctx *context, const NEMTransactionCommon *common, const nem_transaction_ctx *inner, bool cosigning) {
|
||||
bool ret;
|
||||
if (cosigning) {
|
||||
ret = nem_transaction_create_multisig_signature(context,
|
||||
common->network,
|
||||
common->timestamp,
|
||||
NULL,
|
||||
common->fee,
|
||||
common->deadline,
|
||||
inner);
|
||||
} else {
|
||||
ret = nem_transaction_create_multisig(context,
|
||||
common->network,
|
||||
common->timestamp,
|
||||
NULL,
|
||||
common->fee,
|
||||
common->deadline,
|
||||
inner);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to create multisig transaction"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -27,10 +27,16 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
const char *nem_validate_common(NEMTransactionCommon *common);
|
||||
const char *nem_validate_common(NEMTransactionCommon *common, bool inner);
|
||||
const char *nem_validate_transfer(const NEMTransfer *transfer, uint8_t network);
|
||||
|
||||
bool nem_askTransfer(const NEMTransactionCommon *common, const NEMTransfer *transfer);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user