diff --git a/legacy/firmware/layout2.c b/legacy/firmware/layout2.c index 07bc3f6f2..cc6985174 100644 --- a/legacy/firmware/layout2.c +++ b/legacy/firmware/layout2.c @@ -37,6 +37,8 @@ #define BITCOIN_DIVISIBILITY (8) +#if !BITCOIN_ONLY + static const char *slip44_extras(uint32_t coin_type) { if ((coin_type & 0x80000000) == 0) { return 0; @@ -60,6 +62,8 @@ static const char *slip44_extras(uint32_t coin_type) { return 0; } +#endif + #define BIP32_MAX_LAST_ELEMENT 1000000 static const char *address_n_str(const uint32_t *address_n, @@ -98,8 +102,10 @@ static const char *address_n_str(const uint32_t *address_n, legacy = true; } abbr = coin->coin_shortcut + 1; +#if !BITCOIN_ONLY } else { abbr = slip44_extras(address_n[1]); +#endif } } const uint32_t accnum = address_is_account diff --git a/legacy/firmware/signing.c b/legacy/firmware/signing.c index b6be5f4b3..325a91c7b 100644 --- a/legacy/firmware/signing.c +++ b/legacy/firmware/signing.c @@ -48,7 +48,9 @@ enum { STAGE_REQUEST_SEGWIT_INPUT, STAGE_REQUEST_5_OUTPUT, STAGE_REQUEST_SEGWIT_WITNESS, - STAGE_REQUEST_DECRED_WITNESS +#if !BITCOIN_ONLY + STAGE_REQUEST_DECRED_WITNESS, +#endif } signing_stage; static uint32_t idx1, idx2; static uint32_t signatures; @@ -60,7 +62,9 @@ static Hasher hasher_prevouts, hasher_sequence, hasher_outputs, hasher_check; static uint8_t CONFIDENTIAL privkey[32]; static uint8_t pubkey[33], sig[64]; static uint8_t hash_prevouts[32], hash_sequence[32], hash_outputs[32]; -static uint8_t hash_prefix[32]; +#if !BITCOIN_ONLY +static uint8_t decred_hash_prefix[32]; +#endif static uint8_t hash_check[32]; static uint64_t to_spend, authorized_amount, spending, change_spend; static uint32_t version = 1; @@ -68,7 +72,9 @@ static uint32_t lock_time = 0; static uint32_t expiry = 0; static bool overwintered = false; static uint32_t version_group_id = 0; +#if !BITCOIN_ONLY static uint32_t branch_id = 0; +#endif static uint32_t next_nonsegwit_input; static uint32_t progress, progress_step, progress_meta_step; static bool multisig_fp_set, multisig_fp_mismatch; @@ -126,7 +132,7 @@ Phase1 - check inputs, previous transactions, and outputs foreach I (idx1): Request I STAGE_REQUEST_1_INPUT Add I to segwit hash_prevouts, hash_sequence - Add I to Decred hash_prefix + Add I to Decred decred_hash_prefix Add I to TransactionChecksum (prevout and type) if (Decred) Return I @@ -137,8 +143,8 @@ foreach I (idx1): prevhash O (which is amount of I) Request prevhash extra data (if applicable) STAGE_REQUEST_2_PREV_EXTRADATA Calculate hash of streamed tx, compare to prevhash I foreach O (idx1): Request O STAGE_REQUEST_3_OUTPUT Add O to Decred -hash_prefix Add O to TransactionChecksum if (Decred) Return O Display output Ask -for confirmation +decred_hash_prefix Add O to TransactionChecksum if (Decred) Return O Display +output Ask for confirmation Check tx fee Ask for confirmation @@ -186,7 +192,7 @@ Phase3: sign Decred inputs foreach I (idx1): // input to sign STAGE_REQUEST_DECRED_WITNESS Request I Fill scriptSig Compute hash_witness - Sign (hash_type || hash_prefix || hash_witness) + Sign (hash_type || decred_hash_prefix || hash_witness) Return witness */ @@ -306,6 +312,8 @@ void send_req_segwit_witness(void) { msg_write(MessageType_MessageType_TxRequest, &resp); } +#if !BITCOIN_ONLY + void send_req_decred_witness(void) { signing_stage = STAGE_REQUEST_DECRED_WITNESS; resp.has_request_type = true; @@ -316,6 +324,8 @@ void send_req_decred_witness(void) { msg_write(MessageType_MessageType_TxRequest, &resp); } +#endif + void send_req_5_output(void) { signing_stage = STAGE_REQUEST_5_OUTPUT; resp.has_request_type = true; @@ -452,6 +462,7 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, version = msg->version; lock_time = msg->lock_time; expiry = msg->expiry; +#if !BITCOIN_ONLY overwintered = msg->has_overwintered && msg->overwintered; version_group_id = msg->version_group_id; branch_id = msg->branch_id; @@ -466,14 +477,17 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, break; } } +#endif uint32_t size = TXSIZE_HEADER + TXSIZE_FOOTER + ser_length_size(inputs_count) + ser_length_size(outputs_count); +#if !BITCOIN_ONLY if (coin->decred) { size += 4; // Decred expiry size += ser_length_size(inputs_count); // Witness inputs count } +#endif tx_weight = 4 * size; @@ -500,6 +514,7 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, tx_init(&to, inputs_count, outputs_count, version, lock_time, expiry, 0, coin->curve->hasher_sign, overwintered, version_group_id); +#if !BITCOIN_ONLY if (coin->decred) { to.version |= (DECRED_SERIALIZE_FULL << 16); to.is_decred = true; @@ -509,8 +524,10 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, ti.version |= (DECRED_SERIALIZE_NO_WITNESS << 16); ti.is_decred = true; } +#endif // segwit hashes for hashPrevouts and hashSequence +#if !BITCOIN_ONLY if (overwintered) { hasher_InitParam(&hasher_prevouts, HASHER_BLAKE2B_PERSONAL, "ZcashPrevoutHash", 16); @@ -519,7 +536,9 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, hasher_InitParam(&hasher_outputs, HASHER_BLAKE2B_PERSONAL, "ZcashOutputsHash", 16); hasher_Init(&hasher_check, coin->curve->hasher_sign); - } else { + } else +#endif + { hasher_Init(&hasher_prevouts, coin->curve->hasher_sign); hasher_Init(&hasher_sequence, coin->curve->hasher_sign); hasher_Init(&hasher_outputs, coin->curve->hasher_sign); @@ -562,6 +581,7 @@ static bool signing_check_input(const TxInputType *txinput) { // compute segwit hashPrevouts & hashSequence tx_prevout_hash(&hasher_prevouts, txinput); tx_sequence_hash(&hasher_sequence, txinput); +#if !BITCOIN_ONLY if (coin->decred) { if (txinput->decred_script_version > 0) { fsm_sendFailure(FailureType_Failure_DataError, @@ -579,6 +599,7 @@ static bool signing_check_input(const TxInputType *txinput) { // compute Decred hashPrefix tx_serialize_input_hash(&ti, txinput); } +#endif // hash prevout and script type to check it later (relevant for fee // computation) tx_prevout_hash(&hasher_check, txinput); @@ -670,6 +691,7 @@ static bool signing_check_output(TxOutputType *txoutput) { signing_abort(); return false; } +#if !BITCOIN_ONLY if (coin->decred) { // serialize Decred prefix in Phase 1 resp.has_serialized = true; @@ -680,6 +702,7 @@ static bool signing_check_output(TxOutputType *txoutput) { // compute Decred hashPrefix tx_serialize_output_hash(&ti, &bin_output); } +#endif // compute segwit hashOuts tx_output_hash(&hasher_outputs, &bin_output, coin->decred); return true; @@ -737,10 +760,12 @@ static void phase1_request_next_output(void) { idx1++; send_req_3_output(); } else { +#if !BITCOIN_ONLY if (coin->decred) { // compute Decred hashPrefix - tx_hash_final(&ti, hash_prefix, false); + tx_hash_final(&ti, decred_hash_prefix, false); } +#endif hasher_Final(&hasher_outputs, hash_outputs); if (!signing_check_fee()) { return; @@ -749,10 +774,13 @@ static void phase1_request_next_output(void) { progress_meta_step = progress_step / (inputs_count + outputs_count); layoutProgress(_("Signing transaction"), progress); idx1 = 0; +#if !BITCOIN_ONLY if (coin->decred) { // Decred prefix serialized in Phase 1, skip Phase 2 send_req_decred_witness(); - } else { + } else +#endif + { phase2_request_next_input(); } } @@ -777,6 +805,8 @@ static void signing_hash_bip143(const TxInputType *txinput, uint8_t *hash) { hasher_Final(&hasher_preimage, hash); } +#if !BITCOIN_ONLY + static void signing_hash_zip143(const TxInputType *txinput, uint8_t *hash) { uint32_t hash_type = signing_hash_type(); uint8_t personal[16]; @@ -857,11 +887,13 @@ static void signing_hash_decred(const uint8_t *hash_witness, uint8_t *hash) { Hasher hasher_preimage; hasher_Init(&hasher_preimage, coin->curve->hasher_sign); hasher_Update(&hasher_preimage, (const uint8_t *)&hash_type, 4); - hasher_Update(&hasher_preimage, hash_prefix, 32); + hasher_Update(&hasher_preimage, decred_hash_prefix, 32); hasher_Update(&hasher_preimage, hash_witness, 32); hasher_Final(&hasher_preimage, hash); } +#endif + static bool signing_sign_hash(TxInputType *txinput, const uint8_t *private_key, const uint8_t *public_key, const uint8_t *hash) { resp.serialized.has_signature_index = true; @@ -1007,6 +1039,8 @@ static bool signing_sign_segwit_input(TxInputType *txinput) { return true; } +#if !BITCOIN_ONLY + static bool signing_sign_decred_input(TxInputType *txinput) { uint8_t hash[32], hash_witness[32]; tx_hash_final(&ti, hash_witness, false); @@ -1019,6 +1053,8 @@ static bool signing_sign_decred_input(TxInputType *txinput) { return true; } +#endif + #define ENABLE_SEGWIT_NONSEGWIT_MIXING 1 void signing_txack(TransactionType *tx) { @@ -1042,9 +1078,11 @@ void signing_txack(TransactionType *tx) { signing_check_input(&tx->inputs[0]); tx_weight += tx_input_weight(coin, &tx->inputs[0]); +#if !BITCOIN_ONLY if (coin->decred) { tx_weight += tx_decred_witness_weight(&tx->inputs[0]); } +#endif if (tx->inputs[0].script_type == InputScriptType_SPENDMULTISIG || tx->inputs[0].script_type == InputScriptType_SPENDADDRESS) { @@ -1084,12 +1122,14 @@ void signing_txack(TransactionType *tx) { } else if (tx->inputs[0].script_type == InputScriptType_SPENDWITNESS || tx->inputs[0].script_type == InputScriptType_SPENDP2SHWITNESS) { +#if !BITCOIN_ONLY if (coin->decred) { fsm_sendFailure(FailureType_Failure_DataError, _("Decred does not support Segwit")); signing_abort(); return; } +#endif if (!coin->has_segwit) { fsm_sendFailure(FailureType_Failure_DataError, _("Segwit not enabled on this coin")); @@ -1149,10 +1189,12 @@ void signing_txack(TransactionType *tx) { tx_init(&tp, tx->inputs_cnt, tx->outputs_cnt, tx->version, tx->lock_time, tx->expiry, tx->extra_data_len, coin->curve->hasher_sign, overwintered, version_group_id); +#if !BITCOIN_ONLY if (coin->decred) { tp.version |= (DECRED_SERIALIZE_NO_WITNESS << 16); tp.is_decred = true; } +#endif progress_meta_step = progress_step / (tp.inputs_len + tp.outputs_len); idx2 = 0; if (tp.inputs_len > 0) { @@ -1195,6 +1237,7 @@ void signing_txack(TransactionType *tx) { signing_abort(); return; } +#if !BITCOIN_ONLY if (coin->decred && tx->bin_outputs[0].decred_script_version > 0) { fsm_sendFailure( FailureType_Failure_DataError, @@ -1202,6 +1245,7 @@ void signing_txack(TransactionType *tx) { signing_abort(); return; } +#endif to_spend += tx->bin_outputs[0].amount; } if (idx2 < tp.outputs_len - 1) { @@ -1362,6 +1406,7 @@ void signing_txack(TransactionType *tx) { authorized_amount -= tx->inputs[0].amount; uint8_t hash[32]; +#if !BITCOIN_ONLY if (overwintered) { switch (version) { case 3: @@ -1377,7 +1422,9 @@ void signing_txack(TransactionType *tx) { signing_abort(); return; } - } else { + } else +#endif + { signing_hash_bip143(&tx->inputs[0], hash); } if (!signing_sign_hash(&tx->inputs[0], node.private_key, @@ -1477,6 +1524,8 @@ void signing_txack(TransactionType *tx) { } return; +#if !BITCOIN_ONLY + case STAGE_REQUEST_DECRED_WITNESS: progress = 500 + ((signatures * progress_step + idx2 * progress_meta_step) >> @@ -1532,6 +1581,8 @@ void signing_txack(TransactionType *tx) { signing_abort(); } return; + +#endif } fsm_sendFailure(FailureType_Failure_ProcessError, _("Signing error")); diff --git a/legacy/firmware/transaction.c b/legacy/firmware/transaction.c index fb3877549..007324c7e 100644 --- a/legacy/firmware/transaction.c +++ b/legacy/firmware/transaction.c @@ -435,11 +435,15 @@ uint32_t serialize_script_multisig(const CoinInfo *coin, const MultisigRedeemScriptType *multisig, uint8_t sighash, uint8_t *out) { uint32_t r = 0; +#if !BITCOIN_ONLY if (!coin->decred) { // Decred fixed the off-by-one bug +#endif out[r] = 0x00; r++; +#if !BITCOIN_ONLY } +#endif for (uint32_t i = 0; i < multisig->signatures_count; i++) { if (multisig->signatures[i].size == 0) { continue; @@ -813,9 +817,13 @@ static uint32_t tx_input_script_size(const TxInputType *txinput) { } uint32_t tx_input_weight(const CoinInfo *coin, const TxInputType *txinput) { +#if !BITCOIN_ONLY if (coin->decred) { return 4 * (TXSIZE_INPUT + 1); // Decred tree } +#else + (void)coin; +#endif uint32_t input_script_size = tx_input_script_size(txinput); uint32_t weight = 4 * TXSIZE_INPUT; @@ -884,9 +892,11 @@ uint32_t tx_output_weight(const CoinInfo *coin, const TxOutputType *txoutput) { output_script_size += ser_length_size(output_script_size); uint32_t size = TXSIZE_OUTPUT; +#if !BITCOIN_ONLY if (coin->decred) { size += 2; // Decred script version } +#endif return 4 * (size + output_script_size); }