|
|
|
@ -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"));
|
|
|
|
|