1
0
Fork 0
forked from lthn/blockchain

multiple fixes over atomics

This commit is contained in:
cryptozoidberg 2021-02-15 02:17:59 +01:00
parent 06ca6e035d
commit d8f276b30b
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
8 changed files with 96 additions and 49 deletions

View file

@ -1630,9 +1630,9 @@ bool blockchain_storage::purge_altblock_keyimages_from_big_heap(const block& b,
transaction& tx = *tx_ptr;
for (size_t n = 0; n < tx.vin.size(); ++n)
{
if (tx.vin[n].type() == typeid(txin_to_key))
if (tx.vin[n].type() == typeid(txin_to_key) || tx.vin[n].type() == typeid(txin_htlc))
{
purge_keyimage_from_big_heap(boost::get<txin_to_key>(tx.vin[n]).k_image, id);
purge_keyimage_from_big_heap(get_to_key_input_from_txin_v(tx.vin[n]).k_image, id);
}
}
}
@ -4185,13 +4185,12 @@ bool blockchain_storage::have_tx_keyimges_as_spent(const transaction &tx) const
// check all tx's inputs for being already spent
for (const txin_v& in : tx.vin)
{
if (in.type() == typeid(txin_to_key))
if (in.type() == typeid(txin_to_key) || in.type() == typeid(txin_htlc))
{
if (have_tx_keyimg_as_spent(boost::get<const txin_to_key>(in).k_image))
if (have_tx_keyimg_as_spent(get_to_key_input_from_txin_v(in).k_image))
{
return true;
}
}
}
else if (in.type() == typeid(txin_multisig))
{
@ -4264,6 +4263,14 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha
else if (txin.type() == typeid(txin_htlc))
{
const txin_htlc& in_htlc = boost::get<txin_htlc>(txin);
CHECK_AND_ASSERT_MES(in_htlc.key_offsets.size(), false, "Empty in_to_key.key_offsets for input #" << sig_index << " tx: " << tx_prefix_hash);
TIME_MEASURE_START_PD(tx_check_inputs_loop_kimage_check);
if (have_tx_keyimg_as_spent(in_htlc.k_image))
{
LOG_ERROR("Key image was already spent in blockchain: " << string_tools::pod_to_hex(in_htlc.k_image) << " for input #" << sig_index << " tx: " << tx_prefix_hash);
return false;
}
TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_kimage_check);
if (!check_tx_input(tx, sig_index, in_htlc, tx_prefix_hash, *psig, max_used_block_height))
{
LOG_ERROR("Failed to validate multisig input #" << sig_index << " (ms out id: " << obj_to_json_str(in_htlc) << ") in tx: " << tx_prefix_hash);
@ -4763,9 +4770,9 @@ std::shared_ptr<const transaction_chain_entry> blockchain_storage::find_key_imag
}
for (auto& in : tx_chain_entry->tx.vin)
{
if (in.type() == typeid(txin_to_key))
if (in.type() == typeid(txin_to_key) || in.type() == typeid(txin_htlc))
{
if (boost::get<txin_to_key>(in).k_image == ki)
if (get_to_key_input_from_txin_v(in).k_image == ki)
{
id_result = get_transaction_hash(tx_chain_entry->tx);
return tx_chain_entry;

View file

@ -1476,8 +1476,8 @@ namespace currency
sigs.resize(src_entr.outputs.size());
if (!watch_only_mode)
crypto::generate_ring_signature(tx_hash_for_signature, boost::get<txin_to_key>(tx.vin[input_index]).k_image, keys_ptrs, in_contexts[in_context_index].in_ephemeral.sec, src_entr.real_output, sigs.data());
crypto::generate_ring_signature(tx_hash_for_signature, get_to_key_input_from_txin_v(tx.vin[input_index]).k_image, keys_ptrs, in_contexts[in_context_index].in_ephemeral.sec, src_entr.real_output, sigs.data());
ss_ring_s << "signatures:" << ENDL;
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;
@ -1657,8 +1657,8 @@ namespace currency
{
for(const auto& in : tx.vin)
{
CHECK_AND_ASSERT_MES(in.type() == typeid(txin_to_key) || in.type() == typeid(txin_multisig), false, "wrong variant type: "
<< in.type().name() << ", expected " << typeid(txin_to_key).name()
CHECK_AND_ASSERT_MES(in.type() == typeid(txin_to_key) || in.type() == typeid(txin_multisig) || in.type() == typeid(txin_htlc), false, "wrong variant type: "
<< in.type().name()
<< ", in transaction id=" << get_transaction_hash(tx));
}
@ -1775,8 +1775,13 @@ namespace currency
}
else if (in.type() == typeid(txin_multisig))
{
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_multisig, tokey_in, false);
this_amount = tokey_in.amount;
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_multisig, ms_in, false);
this_amount = ms_in.amount;
}
else if (in.type() == typeid(txin_htlc))
{
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_htlc, htlc_in, false);
this_amount = htlc_in.amount;
}
else
{
@ -2370,7 +2375,7 @@ namespace currency
{
for (const auto& e : tx.vin)
{
if (e.type() != typeid(txin_to_key))
if (e.type() != typeid(txin_to_key) || e.type() != typeid(txin_multisig) || e.type() != typeid(txin_htlc))
return false;
if (boost::get<txin_to_key>(e).key_offsets.size() < 2)
return false;
@ -2668,9 +2673,10 @@ namespace currency
{
tei.ins.back().amount = 0;
}
else if (in.type() == typeid(txin_to_key))
else if (in.type() == typeid(txin_to_key) || in.type() == typeid(txin_htlc))
{
txin_to_key& tk = boost::get<txin_to_key>(in);
//TODO: add htlc info
const txin_to_key& tk = get_to_key_input_from_txin_v(in);
tei.ins.back().amount = tk.amount;
tei.ins.back().kimage_or_ms_id = epee::string_tools::pod_to_hex(tk.k_image);
std::vector<txout_ref_v> absolute_offsets = relative_output_offsets_to_absolute(tk.key_offsets);
@ -2687,6 +2693,10 @@ namespace currency
tei.ins.back().global_indexes.back() = std::numeric_limits<uint64_t>::max();
}
}
if (in.type() == typeid(txin_htlc))
{
tei.ins.back().htlc_origin = epee::string_tools::buff_to_hex_nodelimer(boost::get<txin_htlc>(in).hltc_origin);
}
//tk.etc_details -> visualize it may be later
}
else if (in.type() == typeid(txin_multisig))

View file

@ -371,6 +371,8 @@ namespace currency
if (in.type() == typeid(txin_to_key))
return boost::get<txin_to_key>(in).etc_details;
else if (in.type() == typeid(txin_htlc))
return boost::get<txin_htlc>(in).etc_details;
else if (in.type() == typeid(txin_multisig))
return boost::get<txin_multisig>(in).etc_details;
else
@ -502,11 +504,11 @@ namespace currency
}
//---------------------------------------------------------------
template<class add_type_t, class container_type>
extra_t& get_or_add_field_to_variant_vector(container_type& container)
add_type_t& get_or_add_field_to_variant_vector(container_type& container)
{
for (auto& ev : container)
{
if (ev.type() == typeid(exadd_type_ttra_t))
if (ev.type() == typeid(add_type_t))
return boost::get<add_type_t>(ev);
}
container.push_back(add_type_t());
@ -660,6 +662,8 @@ namespace currency
{
if (in.type().hash_code() == typeid(txin_to_key).hash_code())
return &boost::get<txin_to_key>(in).etc_details;
if (in.type().hash_code() == typeid(txin_htlc).hash_code())
return &boost::get<txin_htlc>(in).etc_details;
if (in.type().hash_code() == typeid(txin_multisig).hash_code())
return &boost::get<txin_multisig>(in).etc_details;
return nullptr;
@ -669,6 +673,8 @@ namespace currency
{
if (in.type().hash_code() == typeid(txin_to_key).hash_code())
return &boost::get<txin_to_key>(in).etc_details;
if (in.type().hash_code() == typeid(txin_htlc).hash_code())
return &boost::get<txin_htlc>(in).etc_details;
if (in.type().hash_code() == typeid(txin_multisig).hash_code())
return &boost::get<txin_multisig>(in).etc_details;
return nullptr;

View file

@ -262,10 +262,10 @@ namespace currency
std::unordered_set<crypto::key_image> ki;
BOOST_FOREACH(const auto& in, tx.vin)
{
if (in.type() == typeid(txin_to_key))
if (in.type() == typeid(txin_to_key) || in.type() == typeid(txin_htlc))
{
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
if (!ki.insert(tokey_in.k_image).second)
if (!ki.insert(get_to_key_input_from_txin_v(in).k_image).second)
return false;
}
}

View file

@ -1198,10 +1198,12 @@ namespace currency
{
uint64_t amount;
uint64_t multisig_count;
std::string htlc_origin;
std::string kimage_or_ms_id;
std::vector<uint64_t> global_indexes;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(amount)
KV_SERIALIZE(htlc_origin)
KV_SERIALIZE(kimage_or_ms_id)
KV_SERIALIZE(global_indexes)
KV_SERIALIZE(multisig_count)

View file

@ -398,7 +398,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target.type() == typeid(txout_htlc), "Internal error: wrong index in m_transfers");
//input spend active htlc
m_transfers[it->second].m_spent_height = height;
transfer_details_extra_option_htlc_info& tdeohi = get_or_add_field_to_variant_vector<transfer_details_extra_option_htlc_info>();
transfer_details_extra_option_htlc_info& tdeohi = get_or_add_field_to_variant_vector<transfer_details_extra_option_htlc_info>(td.varian_options);
tdeohi.origin = in_htlc.hltc_origin;
}
}
@ -4029,7 +4029,7 @@ void wallet2::create_htlc_proposal(uint64_t amount, const currency::account_publ
origin = ft.htlc_origin;
}
//----------------------------------------------------------------------------------------------------
void wallet2::get_list_of_active_htlc(bool only_redeem_txs, std::list<wallet_public::htlc_entry_info>& htlcs)
void wallet2::get_list_of_active_htlc(std::list<wallet_public::htlc_entry_info>& htlcs, bool only_redeem_txs)
{
for (auto htlc_entry : m_active_htlcs_txid)
{
@ -4059,7 +4059,12 @@ void wallet2::redeem_htlc(const crypto::hash& htlc_tx_id, std::string origin)
ctp.htlc_origin = origin;
ctp.dsts.resize(1);
ctp.dsts.back().addr.push_back(m_account.get_keys().account_address);
ctp.dsts.back().amount = 0;
auto it = m_active_htlcs_txid.find(htlc_tx_id);
WLT_THROW_IF_FALSE_WITH_CODE(it != m_active_htlcs_txid.end(),
"htlc not found with tx_id = " << htlc_tx_id, API_RETURN_CODE_NOT_FOUND);
ctp.dsts.back().amount = m_transfers[it->second].amount() - ctp.fee;
currency::transaction result_tx = AUTO_VAL_INIT(result_tx);
this->transfer(ctp, result_tx, true, nullptr);

View file

@ -400,7 +400,7 @@ namespace tools
struct transfer_details_extra_option_htlc_info
{
std::string origin; //this field filled only if htlc had been redeemed
}
};
typedef boost::variant<transfer_details_extra_option_htlc_info> transfer_details_extra_options_v;
@ -408,7 +408,7 @@ namespace tools
{
uint64_t m_global_output_index;
crypto::key_image m_key_image; //TODO: key_image stored twice :(
transfer_details_extra_options_v varian_options;
std::vector<transfer_details_extra_options_v> varian_options;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(m_global_output_index)
@ -856,9 +856,8 @@ namespace tools
we use deterministic origin, if given some particular htlc_hash, then we use this hash, and this means that
opener-hash will be given by other side
*/
void create_htlc_proposal(uint64_t amount, const currency::account_public_address& addr, uint64_t lock_blocks_count,
currency::transaction &tx, std::string &origin);
void get_list_of_active_htlc(bool only_redeem_txs, std::list<wallet_public::htlc_entry_info>& htlcs);
void create_htlc_proposal(uint64_t amount, const currency::account_public_address& addr, uint64_t lock_blocks_count, currency::transaction &tx, const crypto::hash& htlc_hash, std::string &origin);
void get_list_of_active_htlc(std::list<wallet_public::htlc_entry_info>& htlcs, bool only_redeem_txs);
void redeem_htlc(const crypto::hash& htlc_tx_id, std::string origin);
bool check_htlc_redeemed(const crypto::hash& htlc_tx_id, std::string& origin);
@ -1077,6 +1076,14 @@ namespace boost
a & x.m_spent_height;
}
template <class Archive>
inline void serialize(Archive &a, tools::wallet2::transfer_details_extra_option_htlc_info &x, const boost::serialization::version_type ver)
{
a & x.origin;
}
template <class Archive>
inline void serialize(Archive &a, tools::wallet2::transfer_details &x, const boost::serialization::version_type ver)
{

View file

@ -124,7 +124,7 @@ bool atomic_simple_test::c1(currency::core& c, size_t ev_index, const std::vecto
std::string alice_origin; //will be deterministically generated by Alice's A wallet
currency::transaction res_tx = AUTO_VAL_INIT(res_tx);
alice_a_wlt_instance->create_htlc_proposal(transfer_amount - TESTS_DEFAULT_FEE, bob_a_wlt_instance->get_account().get_public_address(), 20, res_tx, currency::null_hash, alice_origin);
alice_a_wlt_instance->create_htlc_proposal(transfer_amount - TESTS_DEFAULT_FEE, bob_a_wlt_instance->get_account().get_public_address(), 100, res_tx, currency::null_hash, alice_origin);
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
alice_a_wlt_instance->refresh();
@ -132,19 +132,19 @@ bool atomic_simple_test::c1(currency::core& c, size_t ev_index, const std::vecto
bob_a_wlt_instance->refresh();
bob_b_wlt_instance->refresh();
std::list<wallet_public::htlc_entry_info> htlcs_alice_a;
std::list<tools::wallet_public::htlc_entry_info> htlcs_alice_a;
alice_a_wlt_instance->get_list_of_active_htlc(htlcs_alice_a, false);
CHECK_AND_ASSERT_MES(htlcs_alice_a.size() == 1, false, "htlcs_alice.size() == 1 failed");
std::list<wallet_public::htlc_entry_info> htlcs_bob_a;
std::list<tools::wallet_public::htlc_entry_info> htlcs_bob_a;
bob_a_wlt_instance->get_list_of_active_htlc(htlcs_bob_a, false);
CHECK_AND_ASSERT_MES(htlcs_bob_a.size() == 1, false, "htlcs_bob.size() == 1 failed");
const wallet_public::htlc_entry_info& hei_bob = *htlcs_bob_a.begin();
const tools::wallet_public::htlc_entry_info& hei_bob = *htlcs_bob_a.begin();
CHECK_AND_ASSERT_MES(hei_bob.is_redeem == true, false, "hei_bob.is_redeem == true failed");
const wallet_public::htlc_entry_info& hei_alice = *htlcs_alice_a.begin();
const tools::wallet_public::htlc_entry_info& hei_alice = *htlcs_alice_a.begin();
CHECK_AND_ASSERT_MES(hei_alice.is_redeem == false, false, "hei_alice.is_redeem == false failed");
CHECK_AND_ASSERT_MES(hei_alice.amount == hei_bob.amount
@ -157,7 +157,7 @@ bool atomic_simple_test::c1(currency::core& c, size_t ev_index, const std::vecto
std::string dummy_origin;
bob_b_wlt_instance->create_htlc_proposal(transfer_amount - TESTS_DEFAULT_FEE,
alice_b_wlt_instance->get_account().get_public_address(),
20,
100,
res_tx, hei_bob.sha256_hash, dummy_origin);
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
@ -168,20 +168,25 @@ bool atomic_simple_test::c1(currency::core& c, size_t ev_index, const std::vecto
bob_b_wlt_instance->refresh();
std::list<wallet_public::htlc_entry_info> htlcs_alice_b;
std::list<tools::wallet_public::htlc_entry_info> htlcs_alice_b;
alice_b_wlt_instance->get_list_of_active_htlc(htlcs_alice_b, false);
CHECK_AND_ASSERT_MES(htlcs_alice_b.size() == 1, false, "htlcs_alice_b.size() == 1 failed");
std::list<wallet_public::htlc_entry_info> htlcs_bob_b;
std::list<tools::wallet_public::htlc_entry_info> htlcs_bob_b;
bob_b_wlt_instance->get_list_of_active_htlc(htlcs_bob_b, false);
CHECK_AND_ASSERT_MES(htlcs_bob_b.size() == 1, false, "htlcs_bob_b.size() == 1 failed");
const wallet_public::htlc_entry_info& hei_bob_b = *htlcs_bob_b.begin();
CHECK_AND_ASSERT_MES(hei_bob_b.is_redeem == true, false, "hei_bob_b.is_redeem == true failed");
std::list<tools::wallet_public::htlc_entry_info> htlcs_bob_a_2;
bob_a_wlt_instance->get_list_of_active_htlc(htlcs_bob_a_2, false);
CHECK_AND_ASSERT_MES(htlcs_bob_a_2.size() == 1, false, "htlcs_bob_a.size() == 1 failed");
const wallet_public::htlc_entry_info& hei_alice_b = *htlcs_alice_b.begin();
CHECK_AND_ASSERT_MES(hei_alice_b.is_redeem == false, false, "hei_alice_b.is_redeem == false failed");
const tools::wallet_public::htlc_entry_info& hei_bob_b = *htlcs_bob_b.begin();
CHECK_AND_ASSERT_MES(hei_bob_b.is_redeem == false, false, "hei_bob_b.is_redeem == true failed");
const tools::wallet_public::htlc_entry_info& hei_alice_b = *htlcs_alice_b.begin();
CHECK_AND_ASSERT_MES(hei_alice_b.is_redeem == true, false, "hei_alice_b.is_redeem == false failed");
CHECK_AND_ASSERT_MES(hei_alice_b.amount == hei_bob_b.amount
&& hei_alice_b.sha256_hash == hei_bob_b.sha256_hash
@ -197,19 +202,17 @@ bool atomic_simple_test::c1(currency::core& c, size_t ev_index, const std::vecto
bob_a_wlt_instance->refresh();
bob_b_wlt_instance->refresh();
//htlcs_alice_b.clear();
//alice_b_wlt_instance->get_list_of_active_htlc(htlcs_alice_b, false);
//CHECK_AND_ASSERT_MES(htlcs_alice_b.size() == 0, false, "htlcs_alice_b.size() == 1 failed");
std::list<tools::wallet_public::htlc_entry_info> htlcs_bob_a_3;
bob_a_wlt_instance->get_list_of_active_htlc(htlcs_bob_a_3, false);
CHECK_AND_ASSERT_MES(htlcs_bob_a_3.size() == 1, false, "htlcs_bob_a.size() == 1 failed");
//htlcs_bob_b.clear();
//bob_b_wlt_instance->get_list_of_active_htlc(htlcs_bob_b, false);
//CHECK_AND_ASSERT_MES(htlcs_bob_b.size() == 0, false, "htlcs_bob_b.size() == 1 failed");
std::string bob_detected_origin;
r = bob_b_wlt_instance->check_htlc_redeemed(hei_bob_b.tx_id, bob_detected_origin);
CHECK_AND_ASSERT_MES(r, false, "bob_a_wlt_instance->check_htlc_redeemed(hei_bob_b.tx_id, bob_detected_origin); returned false");
CHECK_AND_ASSERT_MES(bob_detected_origin == alice_origin, false, "bob_detected_origin == alice_origin failed");
bob_b_wlt_instance->redeem_htlc(hei_bob.tx_id, bob_detected_origin);
bob_a_wlt_instance->redeem_htlc(hei_bob.tx_id, bob_detected_origin);
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
@ -219,6 +222,13 @@ bool atomic_simple_test::c1(currency::core& c, size_t ev_index, const std::vecto
bob_a_wlt_instance->refresh();
bob_b_wlt_instance->refresh();
//now we have to check if all balances to make sure that atomic swap passed properly
CHECK_AND_FORCE_ASSERT_MES(alice_a_wlt_instance->balance() == 0, false, "Incorrect balance");
CHECK_AND_FORCE_ASSERT_MES(bob_b_wlt_instance->balance() == 0, false, "Incorrect balance");
CHECK_AND_FORCE_ASSERT_MES(alice_b_wlt_instance->balance() == transfer_amount - TESTS_DEFAULT_FEE, false, "Incorrect balance");
CHECK_AND_FORCE_ASSERT_MES(bob_a_wlt_instance->balance() == transfer_amount - TESTS_DEFAULT_FEE, false, "Incorrect balance");
return r;
}