diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 3673425b..1f5054ef 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -1171,8 +1171,56 @@ namespace currency for (const tx_source_entry& src_entr : sources) { in_contexts.push_back(input_generation_context_data()); - if (!src_entr.is_multisig()) + if(src_entr.is_multisig()) + {//multisig input + txin_multisig input_multisig = AUTO_VAL_INIT(input_multisig); + summary_inputs_money += input_multisig.amount = src_entr.amount; + input_multisig.multisig_out_id = src_entr.multisig_id; + input_multisig.sigs_count = src_entr.ms_sigs_count; + tx.vin.push_back(input_multisig); + } + else if (src_entr.htlc_origin.size()) { + //htlc redeem + keypair& in_ephemeral = in_contexts.back().in_ephemeral; + //txin_to_key + if(src_entr.outputs.size() != 1) + { + LOG_ERROR("htlc in: wrong output src_entr.outputs.size() = " << src_entr.outputs.size()); + return false; + } + summary_inputs_money += src_entr.amount; + + //key_derivation recv_derivation; + crypto::key_image img; + if (!generate_key_image_helper(sender_account_keys, src_entr.real_out_tx_key, src_entr.real_output_in_tx_index, in_ephemeral, img)) + return false; + + //check that derivated key is equal with real output key + if (!(in_ephemeral.pub == src_entr.outputs[src_entr.real_output].second)) + { + LOG_ERROR("derived public key missmatch with output public key! " << ENDL << "derived_key:" + << string_tools::pod_to_hex(in_ephemeral.pub) << ENDL << "real output_public_key:" + << string_tools::pod_to_hex(src_entr.outputs[src_entr.real_output].second)); + return false; + } + + //put key image into tx input + txin_htlc input_to_key; + input_to_key.amount = src_entr.amount; + input_to_key.k_image = img; + input_to_key.hltc_origin = src_entr.htlc_origin; + + //fill outputs array and use relative offsets + BOOST_FOREACH(const tx_source_entry::output_entry& out_entry, src_entr.outputs) + input_to_key.key_offsets.push_back(out_entry.first); + + input_to_key.key_offsets = absolute_output_offsets_to_relative(input_to_key.key_offsets); + tx.vin.push_back(input_to_key); + } + else + { + //regular to key out keypair& in_ephemeral = in_contexts.back().in_ephemeral; //txin_to_key if (src_entr.real_output >= src_entr.outputs.size()) @@ -1197,7 +1245,26 @@ namespace currency } //put key image into tx input - txin_to_key input_to_key; + txin_v in_v; + txin_to_key* ptokey = nullptr; + if (src_entr.htlc_origin.size()) + { + //add txin_htlc + txin_htlc in_htlc = AUTO_VAL_INIT(inp_htlc); + in_htlc.hltc_origin = src_entr.htlc_origin; + in_v = in_htlc; + txin_htlc& in_v_ref = boost::get(in_v); + ptokey = static_cast(&in_v_ref); + } + else + { + in_v = txin_to_key(); + txin_to_key& in_v_ref = boost::get(in_v); + ptokey = &in_v_ref; + } + txin_to_key& input_to_key = *ptokey; + + input_to_key.amount = src_entr.amount; input_to_key.k_image = img; @@ -1206,16 +1273,9 @@ namespace currency input_to_key.key_offsets.push_back(out_entry.first); input_to_key.key_offsets = absolute_output_offsets_to_relative(input_to_key.key_offsets); - tx.vin.push_back(input_to_key); - } - else - {//multisig input - txin_multisig input_multisig = AUTO_VAL_INIT(input_multisig); - summary_inputs_money += input_multisig.amount = src_entr.amount; - input_multisig.multisig_out_id = src_entr.multisig_id; - input_multisig.sigs_count = src_entr.ms_sigs_count; - tx.vin.push_back(input_multisig); + tx.vin.push_back(in_v); } + } // "Shuffle" outs @@ -1302,9 +1362,14 @@ namespace currency tx.signatures.push_back(std::vector()); std::vector& sigs = tx.signatures.back(); - if (!src_entr.is_multisig()) + if(src_entr.is_multisig()) { - // txin_to_key + // txin_multisig -- don't sign anything here (see also sign_multisig_input_in_tx()) + sigs.resize(src_entr.ms_keys_count, null_sig); // just reserve keys.size() null signatures (NOTE: not minimum_sigs!) + } + else + { + // regular txin_to_key or htlc ss_ring_s << "input #" << input_index << ", pub_keys:" << ENDL; std::vector keys_ptrs; BOOST_FOREACH(const tx_source_entry::output_entry& o, src_entr.outputs) @@ -1321,11 +1386,6 @@ namespace currency std::for_each(sigs.begin(), sigs.end(), [&ss_ring_s](const crypto::signature& s) { ss_ring_s << s << ENDL; }); ss_ring_s << "prefix_hash: " << tx_prefix_hash << ENDL << "in_ephemeral_key: " << in_contexts[in_context_index].in_ephemeral.sec << ENDL << "real_output: " << src_entr.real_output << ENDL; } - else - { - // txin_multisig -- don't sign anything here (see also sign_multisig_input_in_tx()) - sigs.resize(src_entr.ms_keys_count, null_sig); // just reserve keys.size() null signatures (NOTE: not minimum_sigs!) - } if (src_entr.separately_signed_tx_complete) { // if separately signed tx is complete, put one more signature to the last bunch using tx secret key, which confirms that transaction has been generated by authorized subject diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 6feb5b07..f355e55c 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -4301,13 +4301,15 @@ bool wallet2::prepare_tx_sources_htlc(crypto::hash htlc_tx_id, const std::string sources.push_back(AUTO_VAL_INIT(currency::tx_source_entry())); currency::tx_source_entry& src = sources.back(); + currency::tx_output_entry real_oe = AUTO_VAL_INIT(real_oe); + real_oe.first = td.m_global_output_index; // TODO: use ref_by_id when necessary + real_oe.second = htlc_out.pkey_redeem; + src.outputs.push_back(real_oe); //m_global_output_index should be prefetched src.amount = found_money = td.amount(); src.real_output_in_tx_index = td.m_internal_output_index; + src.real_output = 0;//no mixins supposed to be in htlc src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_ptx_wallet_info->m_tx); src.htlc_origin = origin; - //src.multisig_id = multisig_id; - //src.ms_sigs_count = ms_out.minimum_sigs; - //src.ms_keys_count = ms_out.keys.size(); return true; } @@ -4880,7 +4882,7 @@ void wallet2::prepare_transaction(const construct_tx_param& ctp, finalize_tx_par else if (ctp.htlc_tx_id != currency::null_hash) { //htlc - bool prepare_tx_sources_htlc(htlc_tx_id, ctp.htlc_origin, sources, found_money); + prepare_tx_sources_htlc(htlc_tx_id, ctp.htlc_origin, sources, found_money); } else if (ctp.multisig_id != currency::null_hash) {