hashes for segwit signature

This commit is contained in:
Jochen Hoenicke 2016-04-29 21:17:06 +02:00 committed by Pavol Rusnak
parent 1bd4b99f95
commit 5c60be9854
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
3 changed files with 57 additions and 11 deletions

View File

@ -50,7 +50,9 @@ static TxInputType input;
static TxOutputBinType bin_output;
static TxStruct to, tp, ti;
static SHA256_CTX tc;
static uint8_t hash[32], hash_check[32], privkey[32], pubkey[33], sig[64];
static SHA256_CTX hashers[2];
static uint8_t hash_check[32], privkey[32], pubkey[33], sig[64];
static uint8_t hash_prevouts[32], hash_sequence[32],hash_outputs[32];
static uint64_t to_spend, spending, change_spend;
static uint32_t version = 1;
static uint32_t lock_time = 0;
@ -273,6 +275,9 @@ void signing_init(uint32_t _inputs_count, uint32_t _outputs_count, const CoinTyp
sha256_Update(&tc, (const uint8_t *)&outputs_count, sizeof(outputs_count));
sha256_Update(&tc, (const uint8_t *)&version, sizeof(version));
sha256_Update(&tc, (const uint8_t *)&lock_time, sizeof(lock_time));
// segwit hashes for hashPrevouts and hashSequence
sha256_Init(&hashers[0]);
sha256_Init(&hashers[1]);
layoutProgressSwipe("Signing transaction", 0);
@ -326,6 +331,9 @@ void signing_txack(TransactionType *tx)
} else { // InputScriptType_SPENDADDRESS
multisig_fp_mismatch = true;
}
// compute segwit hashPrevouts & hashSequence
tx_prevout_hash(&hashers[0], tx->inputs);
tx_sequence_hash(&hashers[1], tx->inputs);
sha256_Update(&tc, (const uint8_t *)tx->inputs, sizeof(TxInputType));
memcpy(&input, tx->inputs, sizeof(TxInputType));
send_req_2_prev_meta();
@ -399,6 +407,8 @@ void signing_txack(TransactionType *tx)
if (tp.extra_data_received < tp.extra_data_len) { // still some data remanining
send_req_2_prev_extradata(tp.extra_data_received, MIN(1024, tp.extra_data_len - tp.extra_data_received));
} else {
/* Check next output */
uint8_t hash[32];
tx_hash_final(&tp, hash, true);
if (memcmp(hash, input.prev_hash.bytes, 32) != 0) {
fsm_sendFailure(FailureType_Failure_Other, "Encountered invalid prevhash");
@ -409,6 +419,13 @@ void signing_txack(TransactionType *tx)
idx1++;
send_req_1_input();
} else {
// compute segwit hashPrevouts & hashSequence
sha256_Final(&hashers[0], hash_prevouts);
sha256_Raw(hash_prevouts, 32, hash_prevouts);
sha256_Final(&hashers[1], hash_sequence);
sha256_Raw(hash_sequence, 32, hash_sequence);
// init hashOutputs
sha256_Init(&hashers[0]);
idx1 = 0;
send_req_3_output();
}
@ -463,11 +480,15 @@ void signing_txack(TransactionType *tx)
signing_abort();
return;
}
// compute segwit hashOuts
tx_output_hash(&hashers[0], &bin_output);
sha256_Update(&tc, (const uint8_t *)&bin_output, sizeof(TxOutputBinType));
if (idx1 < outputs_count - 1) {
idx1++;
send_req_3_output();
} else {
sha256_Final(&hashers[0], hash_outputs);
sha256_Raw(hash_sequence, 32, hash_outputs);
sha256_Final(&tc, hash_check);
// check fees
if (spending > to_spend) {
@ -532,6 +553,7 @@ void signing_txack(TransactionType *tx)
}
tx->inputs[0].script_sig.size = compile_script_multisig(&(tx->inputs[0].multisig), tx->inputs[0].script_sig.bytes);
} else { // SPENDADDRESS
uint8_t hash[20];
ecdsa_get_pubkeyhash(node.public_key, hash);
tx->inputs[0].script_sig.size = compile_script_sig(coin->address_type, hash, tx->inputs[0].script_sig.bytes);
}
@ -580,6 +602,7 @@ void signing_txack(TransactionType *tx)
idx2++;
send_req_4_output();
} else {
uint8_t hash[32];
sha256_Final(&tc, hash);
if (memcmp(hash, hash_check, 32) != 0) {
fsm_sendFailure(FailureType_Failure_Other, "Transaction has changed during signing");

View File

@ -286,6 +286,31 @@ uint32_t serialize_script_multisig(const MultisigRedeemScriptType *multisig, uin
// tx methods
uint32_t tx_prevout_hash(SHA256_CTX *ctx, const TxInputType *input)
{
int i;
for (i = 0; i < 32; i++) {
sha256_Update(ctx, &(input->prev_hash.bytes[31 - i]), 1);
}
sha256_Update(ctx, (const uint8_t *)&input->prev_index, 4);
return 36;
}
uint32_t tx_sequence_hash(SHA256_CTX *ctx, const TxInputType *input)
{
sha256_Update(ctx, (const uint8_t *)&input->sequence, 4);
return 4;
}
uint32_t tx_output_hash(SHA256_CTX *ctx, const TxOutputBinType *output)
{
uint32_t r = 0;
sha256_Update(ctx, (const uint8_t *)&output->amount, 8); r += 8;
r += ser_length_hash(ctx, output->script_pubkey.size);
sha256_Update(ctx, output->script_pubkey.bytes, output->script_pubkey.size); r+= output->script_pubkey.size;
return r;
}
uint32_t tx_serialize_header(TxStruct *tx, uint8_t *out)
{
memcpy(out, &(tx->version), 4);
@ -326,7 +351,6 @@ uint32_t tx_serialize_input(TxStruct *tx, const TxInputType *input, uint8_t *out
uint32_t tx_serialize_input_hash(TxStruct *tx, const TxInputType *input)
{
int i;
if (tx->have_inputs >= tx->inputs_len) {
// already got all inputs
return 0;
@ -335,14 +359,10 @@ uint32_t tx_serialize_input_hash(TxStruct *tx, const TxInputType *input)
if (tx->have_inputs == 0) {
r += tx_serialize_header_hash(tx);
}
for (i = 0; i < 32; i++) {
sha256_Update(&(tx->ctx), &(input->prev_hash.bytes[31 - i]), 1);
}
r += 32;
sha256_Update(&(tx->ctx), (const uint8_t *)&input->prev_index, 4); r += 4;
r += tx_prevout_hash(&(tx->ctx), input);
r += ser_length_hash(&(tx->ctx), input->script_sig.size);
sha256_Update(&(tx->ctx), input->script_sig.bytes, input->script_sig.size); r += input->script_sig.size;
sha256_Update(&(tx->ctx), (const uint8_t *)&input->sequence, 4); r += 4;
r += tx_sequence_hash(&(tx->ctx), input);
tx->have_inputs++;
tx->size += r;
@ -423,9 +443,7 @@ uint32_t tx_serialize_output_hash(TxStruct *tx, const TxOutputBinType *output)
if (tx->have_outputs == 0) {
r += tx_serialize_middle_hash(tx);
}
sha256_Update(&(tx->ctx), (const uint8_t *)&output->amount, 8); r += 8;
r += ser_length_hash(&(tx->ctx), output->script_pubkey.size);
sha256_Update(&(tx->ctx), output->script_pubkey.bytes, output->script_pubkey.size); r+= output->script_pubkey.size;
r += tx_output_hash(&(tx->ctx), output);
tx->have_outputs++;
if (tx->have_outputs == tx->outputs_len) {
r += tx_serialize_footer_hash(tx);

View File

@ -51,6 +51,11 @@ uint32_t compile_script_multisig_hash(const MultisigRedeemScriptType *multisig,
uint32_t serialize_script_sig(const uint8_t *signature, uint32_t signature_len, const uint8_t *pubkey, uint32_t pubkey_len, uint8_t *out);
uint32_t serialize_script_multisig(const MultisigRedeemScriptType *multisig, uint8_t *out);
int compile_output(const CoinType *coin, const HDNode *root, TxOutputType *in, TxOutputBinType *out, bool needs_confirm);
uint32_t tx_prevout_hash(SHA256_CTX *ctx, const TxInputType *input);
uint32_t tx_sequence_hash(SHA256_CTX *ctx, const TxInputType *input);
uint32_t tx_output_hash(SHA256_CTX *ctx, const TxOutputBinType *output);
uint32_t tx_serialize_input(TxStruct *tx, const TxInputType *input, uint8_t *out);
uint32_t tx_serialize_output(TxStruct *tx, const TxOutputBinType *output, uint8_t *out);