diff --git a/firmware/signing.c b/firmware/signing.c index 05cb9054b3..2aff6bd21c 100644 --- a/firmware/signing.c +++ b/firmware/signing.c @@ -478,9 +478,13 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, const HDNode *_root) version = msg->version; lock_time = msg->lock_time; - tx_weight = 4 * (TXSIZE_HEADER + TXSIZE_FOOTER - + ser_length_size(inputs_count) - + ser_length_size(outputs_count)); + uint32_t size = TXSIZE_HEADER + TXSIZE_FOOTER + ser_length_size(inputs_count) + ser_length_size(outputs_count); + if (coin->decred) { + size += 4; // Decred expiry + size += ser_length_size(inputs_count); // Witness inputs count + } + + tx_weight = 4 * size; signatures = 0; idx1 = 0; @@ -904,7 +908,12 @@ void signing_txack(TransactionType *tx) switch (signing_stage) { case STAGE_REQUEST_1_INPUT: signing_check_input(&tx->inputs[0]); - tx_weight += tx_input_weight(&tx->inputs[0]); + + tx_weight += tx_input_weight(coin, &tx->inputs[0]); + if (coin->decred) { + tx_weight += tx_decred_witness_weight(&tx->inputs[0]); + } + if (tx->inputs[0].script_type == InputScriptType_SPENDMULTISIG || tx->inputs[0].script_type == InputScriptType_SPENDADDRESS) { memcpy(&input, tx->inputs, sizeof(TxInputType)); diff --git a/firmware/transaction.c b/firmware/transaction.c index 7f46e61ea1..e99dc75786 100644 --- a/firmware/transaction.c +++ b/firmware/transaction.c @@ -53,6 +53,8 @@ #define TXSIZE_P2PKHASH 25 /* size of a p2sh script (hash, push, 20 scripthash, equal) */ #define TXSIZE_P2SCRIPT 23 +/* size of a Decred witness (without script): 8 amount, 4 block height, 4 block index */ +#define TXSIZE_DECRED_WITNESS 16 static const uint8_t segwit_header[2] = {0,1}; @@ -677,7 +679,7 @@ void tx_hash_final(TxStruct *t, uint8_t *hash, bool reverse) } } -uint32_t tx_input_weight(const TxInputType *txinput) { +static uint32_t tx_input_script_size(const TxInputType *txinput) { uint32_t input_script_size; if (txinput->has_multisig) { uint32_t multisig_script_size = TXSIZE_MULTISIGSCRIPT @@ -688,6 +690,16 @@ uint32_t tx_input_weight(const TxInputType *txinput) { } else { input_script_size = (1 + TXSIZE_SIGNATURE + 1 + TXSIZE_PUBKEY); } + + return input_script_size; +} + +uint32_t tx_input_weight(const CoinInfo *coin, const TxInputType *txinput) { + if (coin->decred) { + return 4 * (TXSIZE_INPUT + 1); // Decred tree + } + + uint32_t input_script_size = tx_input_script_size(txinput); uint32_t weight = 4 * TXSIZE_INPUT; if (txinput->script_type == InputScriptType_SPENDADDRESS || txinput->script_type == InputScriptType_SPENDMULTISIG) { @@ -740,5 +752,18 @@ uint32_t tx_output_weight(const CoinInfo *coin, const TxOutputType *txoutput) { } } output_script_size += ser_length_size(output_script_size); - return 4 * (TXSIZE_OUTPUT + output_script_size); + + uint32_t size = TXSIZE_OUTPUT; + if (coin->decred) { + size += 2; // Decred script version + } + + return 4 * (size + output_script_size); +} + +uint32_t tx_decred_witness_weight(const TxInputType *txinput) { + uint32_t input_script_size = tx_input_script_size(txinput); + uint32_t size = TXSIZE_DECRED_WITNESS + ser_length_size(input_script_size) + input_script_size; + + return 4 * size; } diff --git a/firmware/transaction.h b/firmware/transaction.h index 3695cfc4cc..cd344093ff 100644 --- a/firmware/transaction.h +++ b/firmware/transaction.h @@ -76,7 +76,8 @@ uint32_t tx_serialize_extra_data_hash(TxStruct *tx, const uint8_t *data, uint32_ uint32_t tx_serialize_decred_witness_hash(TxStruct *tx, const TxInputType *input); void tx_hash_final(TxStruct *t, uint8_t *hash, bool reverse); -uint32_t tx_input_weight(const TxInputType *txinput); +uint32_t tx_input_weight(const CoinInfo *coin, const TxInputType *txinput); uint32_t tx_output_weight(const CoinInfo *coin, const TxOutputType *txoutput); +uint32_t tx_decred_witness_weight(const TxInputType *txinput); #endif