From cc007d6d2c042349aabae0aa14dd5dcf6be13184 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Tue, 26 May 2020 19:26:47 +0200 Subject: [PATCH 01/24] Additional checks that all commands that don't check key image have only 1 key_offset --- src/cryptonote_core/blockchain.cpp | 6 +++++- src/safex/command.cpp | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 33183652f..9e195afb6 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -351,7 +351,6 @@ bool Blockchain::scan_outputkeys_for_indexes absolute_offsets; uint64_t value_amount = 0; diff --git a/src/safex/command.cpp b/src/safex/command.cpp index 0daf7dce4..86cf4d2b2 100644 --- a/src/safex/command.cpp +++ b/src/safex/command.cpp @@ -552,6 +552,11 @@ namespace safex //parse command and validate it try { + if(!safex::is_safex_key_image_verification_needed(txin.command_type) && txin.key_offsets.size() != 1) + { + LOG_ERROR("Commands that don't have key image verification must have only 1 key offset"); + return false; + } std::unique_ptr cmd = safex_command_serializer::parse_safex_object(txin.script, txin.command_type); execution_status result{cmd->validate(blokchainDB, txin)}; if (result != execution_status::ok) From 2f2c3fa014db58bd813b13ce0696074ff5da1a61 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Wed, 27 May 2020 11:54:38 +0200 Subject: [PATCH 02/24] Only 1 key for tx_out_to_script is used --- src/blockchain_db/lmdb/db_lmdb.cpp | 4 ++-- src/cryptonote_basic/cryptonote_basic.h | 6 ++--- .../cryptonote_boost_serialization.h | 2 +- src/cryptonote_core/cryptonote_tx_utils.cpp | 22 +++++++++---------- src/serialization/json_object.cpp | 4 ++-- tests/core_tests/tx_validation.cpp | 4 ++-- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index ee932c107..22df06444 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1250,7 +1250,7 @@ uint64_t BlockchainLMDB::add_advanced_output(const tx_out& tx_output, const uint okadv.height = blockchain_height; okadv.unlock_time = unlock_time; okadv.output_id = output_id; - okadv.pubkey = txout.keys[0]; //todo if there are multiple keys, rest will go to data + okadv.pubkey = txout.key; //todo if there are multiple keys, rest will go to data okadv.data = blobdata(txout.data.begin(),txout.data.end()); //no need to serialize vector to blob. Just copy it. MDB_val_copy adv_value(okadv); @@ -3489,7 +3489,7 @@ bool BlockchainLMDB::for_all_advanced_outputs(std::function(output.output_type); - txout.keys.push_back(output.pubkey); //todo handle case where there are multiple keys, and some are in data + txout.key = output.pubkey; parse_and_validate_byte_array_from_blob(output.data, txout.data); diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index 347ae77e4..67c1eebdc 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -63,14 +63,14 @@ namespace cryptonote struct txout_to_script { - std::vector keys; + crypto::public_key key; std::vector data; //Local output data and state uint8_t output_type{0}; BEGIN_SERIALIZE_OBJECT() VARINT_FIELD(output_type) - FIELD(keys) + FIELD(key) FIELD(data) END_SERIALIZE() }; @@ -115,7 +115,7 @@ namespace cryptonote boost::optional operator()(const cryptonote::txout_to_script &txout) const { - return txout.keys[0]; + return txout.key; } }; diff --git a/src/cryptonote_basic/cryptonote_boost_serialization.h b/src/cryptonote_basic/cryptonote_boost_serialization.h index 46764ae11..465615dc0 100644 --- a/src/cryptonote_basic/cryptonote_boost_serialization.h +++ b/src/cryptonote_basic/cryptonote_boost_serialization.h @@ -94,7 +94,7 @@ namespace boost inline void serialize(Archive &a, cryptonote::txout_to_script &x, const boost::serialization::version_type ver) { a & x.output_type; - a & x.keys; + a & x.key; a & x.data; } diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index f69830001..f89f35c07 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -1411,7 +1411,7 @@ namespace cryptonote txout_to_script txs = AUTO_VAL_INIT(txs); txs.output_type = static_cast(cryptonote::tx_out_type::out_staked_token); - txs.keys.push_back(out_eph_public_key); + txs.key = out_eph_public_key; //find matching script input const std::vector matched_inputs = match_inputs(dst_entr, sources, tx.vin); SAFEX_COMMAND_CHECK_AND_ASSERT_THROW_MES(matched_inputs.size() > 0, "Missing command on inputs to create token stake output", safex::command_t::token_stake); @@ -1428,7 +1428,7 @@ namespace cryptonote txout_to_script txs = AUTO_VAL_INIT(txs); txs.output_type = static_cast(tx_out_type::out_network_fee); - txs.keys.push_back(out_eph_public_key); + txs.key = out_eph_public_key; //find matching script input const std::vector matched_inputs = match_inputs(dst_entr, sources, tx.vin); SAFEX_COMMAND_CHECK_AND_ASSERT_THROW_MES(matched_inputs.size() > 0, "Missing command on inputs to create network fee output", safex::command_t::donate_network_fee); @@ -1446,7 +1446,7 @@ namespace cryptonote txout_to_script txs = AUTO_VAL_INIT(txs); txs.output_type = static_cast(tx_out_type::out_safex_account); - txs.keys.push_back(sfx_acc_keys.get_public_key()); + txs.key = sfx_acc_keys.m_public_key; txs.data = std::vector(std::begin(dst_entr.output_data), std::end(dst_entr.output_data)); //find matching script input @@ -1460,7 +1460,7 @@ namespace cryptonote { txout_to_script txs = AUTO_VAL_INIT(txs); txs.output_type = static_cast(tx_out_type::out_safex_account_update); - txs.keys.push_back(sfx_acc_keys.m_public_key); + txs.key = sfx_acc_keys.m_public_key; txs.data = std::vector(std::begin(dst_entr.output_data), std::end(dst_entr.output_data)); //find matching script input @@ -1474,7 +1474,7 @@ namespace cryptonote { txout_to_script txs = AUTO_VAL_INIT(txs); txs.output_type = static_cast(tx_out_type::out_safex_offer); - txs.keys.push_back(sfx_acc_keys.m_public_key); + txs.key = sfx_acc_keys.m_public_key; txs.data = std::vector(std::begin(dst_entr.output_data), std::end(dst_entr.output_data)); //find matching script input @@ -1488,7 +1488,7 @@ namespace cryptonote { txout_to_script txs = AUTO_VAL_INIT(txs); txs.output_type = static_cast(tx_out_type::out_safex_offer_update); - txs.keys.push_back(sfx_acc_keys.m_public_key); + txs.key = sfx_acc_keys.m_public_key; txs.data = std::vector(std::begin(dst_entr.output_data), std::end(dst_entr.output_data)); //find matching script input @@ -1503,7 +1503,7 @@ namespace cryptonote out.token_amount = 0; txout_to_script txs = AUTO_VAL_INIT(txs); txs.output_type = static_cast(tx_out_type::out_safex_purchase); - txs.keys.push_back(out_eph_public_key); + txs.key = out_eph_public_key; txs.data = std::vector(std::begin(dst_entr.output_data), std::end(dst_entr.output_data)); //find matching script input @@ -1518,7 +1518,7 @@ namespace cryptonote out.token_amount = 0; txout_to_script txs = AUTO_VAL_INIT(txs); txs.output_type = static_cast(tx_out_type::out_safex_feedback_token); - txs.keys.push_back(out_eph_public_key); + txs.key = out_eph_public_key; txs.data = std::vector(std::begin(dst_entr.output_data), std::end(dst_entr.output_data)); //find matching script input @@ -1533,7 +1533,7 @@ namespace cryptonote out.token_amount = 0; txout_to_script txs = AUTO_VAL_INIT(txs); txs.output_type = static_cast(tx_out_type::out_safex_feedback); - txs.keys.push_back(out_eph_public_key); + txs.key = out_eph_public_key; txs.data = std::vector(std::begin(dst_entr.output_data), std::end(dst_entr.output_data)); //find matching script input @@ -1547,7 +1547,7 @@ namespace cryptonote { txout_to_script txs = AUTO_VAL_INIT(txs); txs.output_type = static_cast(tx_out_type::out_safex_price_peg); - txs.keys.push_back(sfx_acc_keys.m_public_key); + txs.key = sfx_acc_keys.m_public_key; txs.data = std::vector(std::begin(dst_entr.output_data), std::end(dst_entr.output_data)); //find matching script input @@ -1561,7 +1561,7 @@ namespace cryptonote { txout_to_script txs = AUTO_VAL_INIT(txs); txs.output_type = static_cast(tx_out_type::out_safex_price_peg_update); - txs.keys.push_back(sfx_acc_keys.m_public_key); + txs.key = sfx_acc_keys.m_public_key; txs.data = std::vector(std::begin(dst_entr.output_data), std::end(dst_entr.output_data)); //find matching script input diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp index 06afc8920..c7e92d487 100644 --- a/src/serialization/json_object.cpp +++ b/src/serialization/json_object.cpp @@ -572,7 +572,7 @@ void toJsonValue(rapidjson::Document& doc, const cryptonote::txout_to_script& tx val.SetObject(); INSERT_INTO_JSON_OBJECT(val, doc, script, txout.output_type); - INSERT_INTO_JSON_OBJECT(val, doc, keys, txout.keys); + INSERT_INTO_JSON_OBJECT(val, doc, key, txout.key); INSERT_INTO_JSON_OBJECT(val, doc, data, txout.data); } @@ -585,7 +585,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_script& txo } GET_FROM_JSON_OBJECT(val, txout.output_type, script); - GET_FROM_JSON_OBJECT(val, txout.keys, keys); + GET_FROM_JSON_OBJECT(val, txout.key, key); GET_FROM_JSON_OBJECT(val, txout.data, data); } diff --git a/tests/core_tests/tx_validation.cpp b/tests/core_tests/tx_validation.cpp index f25457977..848678d78 100644 --- a/tests/core_tests/tx_validation.cpp +++ b/tests/core_tests/tx_validation.cpp @@ -117,7 +117,7 @@ namespace if (dst_entr.output_type == tx_out_type::out_staked_token) { txout_to_script ts; - ts.keys.push_back(out_eph_public_key); + ts.key = out_eph_public_key; ts.output_type = static_cast(tx_out_type::out_staked_token); out.target = ts; @@ -865,4 +865,4 @@ bool gen_tx_not_enough_tokens_to_lock::generate(std::vector& e MAKE_TX_TOKEN_LOCK_LIST_START(events, txlist_1, alice, MK_TOKENS(1000), blk_4); return true; -} \ No newline at end of file +} From 21c5494435558a68e14a15a4c70c1b1257c21445 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Thu, 28 May 2020 16:43:34 +0200 Subject: [PATCH 03/24] Call abort function when error in add_transaction --- src/blockchain_db/blockchain_db.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp index ec1e578d9..dd67aea85 100644 --- a/src/blockchain_db/blockchain_db.cpp +++ b/src/blockchain_db/blockchain_db.cpp @@ -253,11 +253,19 @@ uint64_t BlockchainDB::add_block( const block& blk add_transaction(blk_hash, blk.miner_tx); int tx_i = 0; crypto::hash tx_hash = crypto::null_hash; - for (const transaction& tx : txs) + try { - tx_hash = blk.tx_hashes[tx_i]; - add_transaction(blk_hash, tx, &tx_hash); - ++tx_i; + for (const transaction& tx : txs) + { + tx_hash = blk.tx_hashes[tx_i]; + add_transaction(blk_hash, tx, &tx_hash); + ++tx_i; + } + } + catch(SAFEX_TX_CONFLICT& e) + { + block_txn_abort(); + throw e; } TIME_MEASURE_FINISH(time1); time_add_transaction += time1; From 047ee4c2929b1658761862c2cefb02d73c4e7073 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Thu, 28 May 2020 17:44:23 +0200 Subject: [PATCH 04/24] Add safex checks before adding block to the main_chain --- src/cryptonote_core/blockchain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 9e195afb6..ce5776a85 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -5009,7 +5009,7 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash& { // validate that transaction inputs and the keys spending them are correct. tx_verification_context tvc; - if(!check_tx_inputs(tx, tvc)) + if(!check_tx_inputs(tx, tvc) || !check_safex_tx(tx, tvc)) { MERROR_VER("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs."); From 573d7975178e6ec399d84d23d529b70dae033712 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Thu, 28 May 2020 17:45:26 +0200 Subject: [PATCH 05/24] Remove also miner_tx when reverting transactions --- src/cryptonote_core/blockchain.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index ce5776a85..85b2d7223 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -5098,6 +5098,7 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash& } catch (const SAFEX_TX_CONFLICT& e){ + m_db->revert_transaction(bl.miner_tx.hash); for(auto tx: txs){ cryptonote::transaction tmp; if(m_db->get_tx(tx.hash,tmp)) @@ -5113,6 +5114,7 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash& catch (const std::exception& e) { + m_db->revert_transaction(bl.miner_tx.hash); for(auto tx: txs){ cryptonote::transaction tmp; if(m_db->get_tx(tx.hash,tmp)) From 18a1228e35ba7e69d4ab0126739f0fb97e7ac6d9 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Thu, 28 May 2020 19:55:19 +0200 Subject: [PATCH 06/24] Add check_safex_tx inside check_tx_inputs --- src/cryptonote_core/blockchain.cpp | 8 +++++++- src/cryptonote_core/tx_pool.cpp | 7 ------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 85b2d7223..2eeea4df9 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -4205,6 +4205,12 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, sig_index++; } + if(!check_safex_tx(tx,tvc)){ + tvc.m_verifivation_failed = true; + tvc.m_safex_verification_failed = true; + return false; + } + if ((tx.version >= HF_VERSION_MIN_SUPPORTED_TX_VERSION && tx.version <= HF_VERSION_MAX_SUPPORTED_TX_VERSION) && threads > 1) waiter.wait(); @@ -5009,7 +5015,7 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash& { // validate that transaction inputs and the keys spending them are correct. tx_verification_context tvc; - if(!check_tx_inputs(tx, tvc) || !check_safex_tx(tx, tvc)) + if(!check_tx_inputs(tx, tvc)) { MERROR_VER("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs."); diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index a39450912..36c58794a 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -194,13 +194,6 @@ namespace cryptonote return false; } - //Here check for tx related safex logic - if ( !kept_by_block && (tx.version > HF_VERSION_MIN_SUPPORTED_TX_VERSION) && !m_blockchain.check_safex_tx(tx, tvc)) - { - tvc.m_verifivation_failed = true; - tvc.m_safex_verification_failed = true; - return false; - } } else { From 996a04120f1f2426764c2c771c287cc1824422d6 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Fri, 29 May 2020 18:02:27 +0200 Subject: [PATCH 07/24] Skip callbacks for outputs that don't use key images in the wallet --- src/wallet/wallet.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f173e0cf1..314a1f2e3 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1360,7 +1360,8 @@ void wallet::process_new_transaction(const crypto::hash &txid, const cryptonote: const crypto::key_image &k_image = *boost::apply_visitor(key_image_visitor(), in); auto it = m_key_images.find(k_image); - if(it != m_key_images.end()) + if (it != m_key_images.end() && + (in.type() != typeid(txin_to_script) || safex::is_safex_key_image_verification_needed(boost::get(in).command_type))) { transfer_details& td = m_transfers[it->second]; uint64_t value_amount = *boost::apply_visitor(amount_visitor(), in); @@ -11592,7 +11593,8 @@ uint64_t wallet::import_key_images(const std::vector(in).command_type))) { const transfer_details& td = m_transfers[it->second]; uint64_t value_amount = *boost::apply_visitor(amount_visitor(), in); From d4ad54a68b76924c88ed60ccbe5e00e929aed57a Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Fri, 29 May 2020 18:03:24 +0200 Subject: [PATCH 08/24] Fix for detecting type of tx --- src/cryptonote_basic/cryptonote_basic.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index 67c1eebdc..29acd66e2 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -683,7 +683,8 @@ namespace cryptonote break; default: if(get_tx_out_type(it.target) >= tx_out_type::out_advanced && get_tx_out_type(it.target) < tx_out_type::out_invalid - && (tx_type < get_tx_out_type(it.target) || tx_type == tx_out_type::out_invalid)){ + && ((tx_type < get_tx_out_type(it.target) && tx_type != tx_out_type::out_safex_purchase) + || tx_type == tx_out_type::out_invalid)){ tx_type = get_tx_out_type(it.target); advanced_seen = true; } From 897f9ea77b33e894ed80ab8ad22f48cdeaf072ca Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Fri, 29 May 2020 18:06:03 +0200 Subject: [PATCH 09/24] Fix for block mining from txs in the pool. Add check for total purchase quantity if it is not oveflowing the quantity from the blockchain --- src/cryptonote_core/tx_pool.cpp | 58 +++++++++++++++++++++++++++------ src/cryptonote_core/tx_pool.h | 10 ++++++ 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 36c58794a..abc6c5c51 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -1242,7 +1242,7 @@ namespace cryptonote if(true) { //if we already failed on this height and id, skip actual ring signature check - if(txd.last_failed_id == m_blockchain.get_block_id_by_height(txd.last_failed_height)) + if(txd.last_failed_id == m_blockchain.get_block_id_by_height(m_blockchain.get_current_blockchain_height()-1)) return false; //check ring signature again, it is possible (with very small chance) that this transaction become again valid tx_verification_context tvc; @@ -1265,6 +1265,42 @@ namespace cryptonote return true; } //--------------------------------------------------------------------------------- + bool tx_memory_pool::is_purchase_possible(txpool_tx_meta_t& txd, transaction &tx, std::unordered_map& offer_quantity_left) const + { + if(get_tx_type(tx.vout) != tx_out_type::out_safex_purchase) + return true; + + for (auto vout: tx.vout) + { + if (vout.target.type() == typeid(txout_to_script) && get_tx_out_type(vout.target) == cryptonote::tx_out_type::out_safex_purchase) + { + const txout_to_script &out = boost::get(vout.target); + safex::create_purchase_data purchase; + const cryptonote::blobdata purchaseblob(std::begin(out.data), std::end(out.data)); + cryptonote::parse_and_validate_from_blob(purchaseblob, purchase); + + if(offer_quantity_left.count(purchase.offer_id) == 0){ + uint64_t quantity; + auto res = m_blockchain.get_safex_offer_quantity(purchase.offer_id, quantity); + if(!res){ + txd.last_failed_height = m_blockchain.get_current_blockchain_height()-1; + txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height); + return false; + } + offer_quantity_left[purchase.offer_id] = quantity; + } + if(offer_quantity_left[purchase.offer_id] < purchase.quantity){ + txd.last_failed_height = m_blockchain.get_current_blockchain_height()-1; + txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height); + return false; + } + offer_quantity_left[purchase.offer_id] -= purchase.quantity; + } + } + + return true; + } + //--------------------------------------------------------------------------------- bool tx_memory_pool::have_key_images(const std::unordered_set& k_images, const transaction& tx) { for(size_t i = 0; i!= tx.vin.size(); i++) @@ -1409,6 +1445,8 @@ namespace cryptonote LockedTXN lock(m_blockchain); + std::unordered_map offer_quantity_left; + auto sorted_it = m_txs_by_fee_and_receive_time.begin(); while (sorted_it != m_txs_by_fee_and_receive_time.end()) { @@ -1472,18 +1510,18 @@ namespace cryptonote // included into the blockchain or that are // missing key images const cryptonote::txpool_tx_meta_t original_meta = meta; - bool ready = is_transaction_ready_to_go(meta, tx); + bool ready = is_transaction_ready_to_go(meta, tx) && is_purchase_possible(meta, tx, offer_quantity_left); if (memcmp(&original_meta, &meta, sizeof(meta))) { try - { - m_blockchain.update_txpool_tx(sorted_it->second, meta); - } - catch (const std::exception &e) - { - MERROR("Failed to update tx meta: " << e.what()); - // continue, not fatal - } + { + m_blockchain.update_txpool_tx(sorted_it->second, meta); + } + catch (const std::exception &e) + { + MERROR("Failed to update tx meta: " << e.what()); + // continue, not fatal + } } if (!ready) { diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index db68bb0a5..e5982b788 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -564,6 +564,16 @@ namespace cryptonote */ bool is_transaction_ready_to_go(txpool_tx_meta_t& txd, transaction &tx) const; + /** + * @brief check if a transaction is a purchase that can be included in a block + * + * @param txd the transaction to check (and info about it) + * @param tx the transaction to check + * @param offer_quantity_left quantity of offers after commiting purchases before this tx + * + * @return true if the transaction is good to go, otherwise false + */ + bool is_purchase_possible(txpool_tx_meta_t& txd, transaction &tx, std::unordered_map& offer_quantity_left) const; /** * @brief mark all transactions double spending the one passed */ From 378ecc89a069990537e0f7678fcf200a008dee8f Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Fri, 29 May 2020 18:07:34 +0200 Subject: [PATCH 10/24] Do not remove tx when returning to the pool as now pool can handle it. Move check_safex_tx so we don't mess up with the threads. --- src/cryptonote_core/blockchain.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 2eeea4df9..93145f560 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -4205,12 +4205,6 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, sig_index++; } - if(!check_safex_tx(tx,tvc)){ - tvc.m_verifivation_failed = true; - tvc.m_safex_verification_failed = true; - return false; - } - if ((tx.version >= HF_VERSION_MIN_SUPPORTED_TX_VERSION && tx.version <= HF_VERSION_MAX_SUPPORTED_TX_VERSION) && threads > 1) waiter.wait(); @@ -4243,6 +4237,12 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, return false; } + if(!check_safex_tx(tx,tvc)){ + tvc.m_verifivation_failed = true; + tvc.m_safex_verification_failed = true; + return false; + } + return true; } @@ -5110,8 +5110,6 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash& if(m_db->get_tx(tx.hash,tmp)) m_db->revert_transaction(tx.hash); } - auto it = find_if(txs.begin(),txs.end(),[e](transaction& tx){ return tx.hash == e.tx_hash; }); - txs.erase(it); LOG_ERROR("Error adding block with hash: " << id << " to blockchain, what = " << e.what()); bvc.m_verifivation_failed = true; return_tx_to_pool(txs); From c6611264f9e0675a4bcf094b7335ea0d7e70e35a Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Sat, 30 May 2020 11:13:28 +0200 Subject: [PATCH 11/24] Include txs in the pool that do not need key_image verification --- src/cryptonote_core/tx_pool.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index abc6c5c51..c9550f256 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -1321,15 +1321,22 @@ namespace cryptonote //--------------------------------------------------------------------------------- bool tx_memory_pool::append_key_images(std::unordered_set& k_images, const transaction& tx) { - for(size_t i = 0; i!= tx.vin.size(); i++) + for(auto& txin: tx.vin) { - if (cryptonote::is_valid_transaction_input_type(tx.vin[i], tx.version)) { - auto k_image_opt = boost::apply_visitor(key_image_visitor(), tx.vin[i]); + if (txin.type() == typeid(txin_to_script)) + { + const txin_to_script& in_to_script = boost::get(txin); + if(!safex::is_safex_key_image_verification_needed(in_to_script.command_type)) + continue; + } + + if (cryptonote::is_valid_transaction_input_type(txin, tx.version)) { + auto k_image_opt = boost::apply_visitor(key_image_visitor(), txin); CHECK_AND_ASSERT_MES(k_image_opt, false, "key image available in input is not valid"); auto i_res = k_images.insert(*k_image_opt); CHECK_AND_ASSERT_MES(i_res.second, false, "internal error: key images pool cache - inserted duplicate image in set: " << *k_image_opt); } else { - LOG_ERROR("wrong input variant type: " << tx.vin[i].type().name() << ", expected " << typeid(txin_to_key).name() << ", " << typeid(txin_token_to_key).name() << " or " << typeid(txin_token_migration).name()); + LOG_ERROR("wrong input variant type: " << txin.type().name() << ", expected " << typeid(txin_to_key).name() << ", " << typeid(txin_token_to_key).name() << " or " << typeid(txin_token_migration).name()); return false; } } From e6f4898100cb74d4b6a2e899693d8c1bcf4582e2 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Sat, 30 May 2020 11:41:23 +0200 Subject: [PATCH 12/24] Fix in calculation of network interest --- src/wallet/wallet_safex.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wallet/wallet_safex.cpp b/src/wallet/wallet_safex.cpp index 535ee9812..a75fab8dc 100644 --- a/src/wallet/wallet_safex.cpp +++ b/src/wallet/wallet_safex.cpp @@ -167,8 +167,8 @@ namespace tools cryptonote::COMMAND_RPC_GET_INTEREST_MAP::request req = AUTO_VAL_INIT(req); cryptonote::COMMAND_RPC_GET_INTEREST_MAP::response res = AUTO_VAL_INIT(res); - req.begin_interval = safex::calculate_interval_for_height(start_interval, this->nettype()) + 1; //earning interest starts from next interval - req.end_interval = safex::calculate_interval_for_height(end_interval, this->nettype()) - 1; //finishes in previous interval + req.begin_interval = start_interval; + req.end_interval = end_interval; if (req.begin_interval > req.end_interval) return interest_map; @@ -208,8 +208,8 @@ namespace tools return 0; } - auto begin_interval = td.m_block_height; - auto end_interval = this->get_blockchain_current_height(); + auto begin_interval = safex::calculate_interval_for_height(td.m_block_height, this->nettype()) + 1; //earning interest starts from next interval + auto end_interval = safex::calculate_interval_for_height(this->get_blockchain_current_height(), this->nettype()) - 1; //finishes in previous interval auto interest_map = get_interest_map(begin_interval, end_interval); From b1b2eff3341bb551848dd57b83a4b5dfbdafe621 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Sun, 31 May 2020 16:58:00 +0200 Subject: [PATCH 13/24] Fix for detecting type of tx --- src/cryptonote_basic/cryptonote_basic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index 29acd66e2..bf2a8a922 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -683,7 +683,7 @@ namespace cryptonote break; default: if(get_tx_out_type(it.target) >= tx_out_type::out_advanced && get_tx_out_type(it.target) < tx_out_type::out_invalid - && ((tx_type < get_tx_out_type(it.target) && tx_type != tx_out_type::out_safex_purchase) + && ((tx_type < get_tx_out_type(it.target) && tx_type != tx_out_type::out_safex_purchase) || get_tx_out_type(it.target) == tx_out_type::out_safex_purchase || tx_type == tx_out_type::out_invalid)){ tx_type = get_tx_out_type(it.target); advanced_seen = true; From 1b55b187d67b4b0b453e0bb382918ac96c13df25 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Sun, 31 May 2020 17:24:55 +0200 Subject: [PATCH 14/24] Lower the log of validation as there is a case when it is not fatal now --- src/safex/command.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/safex/command.cpp b/src/safex/command.cpp index 86cf4d2b2..dd2981701 100644 --- a/src/safex/command.cpp +++ b/src/safex/command.cpp @@ -561,7 +561,7 @@ namespace safex execution_status result{cmd->validate(blokchainDB, txin)}; if (result != execution_status::ok) { - LOG_ERROR("Validation of safex command failed, status:" << static_cast(result)); + LOG_PRINT_L1("Validation of safex command failed, status:" << static_cast(result)); return false; } } From 634306a471b7494fd34890ff6904575ff58eb51d Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Sun, 31 May 2020 17:26:08 +0200 Subject: [PATCH 15/24] Add safex related field in txpool_tx_meta_t --- src/blockchain_db/blockchain_db.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 8d1117f88..c75791810 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -172,8 +172,9 @@ namespace cryptonote uint8_t relayed; uint8_t do_not_relay; uint8_t double_spend_seen: 1; + uint8_t safex_failed; - uint8_t padding[76]; // till 192 bytes + uint8_t padding[75]; // till 192 bytes }; #define DBF_SAFE 1 From 4a42a779f2f2fb0b48b867722680449a81e11bb6 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Sun, 31 May 2020 17:26:34 +0200 Subject: [PATCH 16/24] On blockchain new block added, check if any tx in the pool is failing safex logic. If it is, mark it and remove it when possible --- src/cryptonote_core/tx_pool.cpp | 50 ++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index c9550f256..604569f93 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -696,7 +696,8 @@ namespace cryptonote uint64_t tx_age = time(nullptr) - meta.receive_time; if((tx_age > CRYPTONOTE_MEMPOOL_TX_LIVETIME && !meta.kept_by_block) || - (tx_age > CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME && meta.kept_by_block) ) + (tx_age > CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME && meta.kept_by_block) || + meta.safex_failed) { LOG_PRINT_L1("Tx " << txid << " removed from tx pool due to outdated, age: " << tx_age ); auto sorted_it = find_tx_in_sorted_container(txid); @@ -1075,6 +1076,53 @@ namespace cryptonote //--------------------------------------------------------------------------------- bool tx_memory_pool::on_blockchain_inc(uint64_t new_block_height, const crypto::hash& top_block_id) { + + CRITICAL_REGION_LOCAL(m_transactions_lock); + CRITICAL_REGION_LOCAL1(m_blockchain); + + LockedTXN lock(m_blockchain); + + for(auto& sorted_it : m_txs_by_fee_and_receive_time) + { + txpool_tx_meta_t meta; + + if (!m_blockchain.get_txpool_tx_meta(sorted_it.second, meta)) + { + MERROR(" failed to find tx meta"); + continue; + } + + cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(sorted_it.second); + cryptonote::transaction tx; + if (!parse_and_validate_tx_from_blob(txblob, tx)) + { + MERROR("Failed to parse tx from txpool"); + continue; + } + + // Skip transactions that are not ready to be + // included into the blockchain or that are + // missing key images + const cryptonote::txpool_tx_meta_t original_meta = meta; + tx_verification_context tvc; + if(!m_blockchain.check_tx_inputs(tx, meta.max_used_block_height, meta.max_used_block_id, tvc)) + { + meta.safex_failed = tvc.m_safex_invalid_input || tvc.m_safex_invalid_command || tvc.m_safex_verification_failed || + tvc.m_safex_invalid_command_params || tvc.m_safex_command_execution_failed; + } + if (memcmp(&original_meta, &meta, sizeof(meta))) + { + try + { + m_blockchain.update_txpool_tx(sorted_it.second, meta); + } + catch (const std::exception &e) + { + MERROR("Failed to update tx meta: " << e.what()); + // continue, not fatal + } + } + } return true; } //--------------------------------------------------------------------------------- From 2237f9ba498ce34f95fa2ec1bfaf86814e8f5a3a Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Mon, 1 Jun 2020 12:53:07 +0200 Subject: [PATCH 17/24] Small refactor --- src/cryptonote_basic/cryptonote_basic.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index bf2a8a922..27105f017 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -670,7 +670,8 @@ namespace cryptonote bool token_seen = false; bool advanced_seen = false; for(auto it: vout){ - switch(get_tx_out_type(it.target)){ + auto curr_tx_out_type = get_tx_out_type(it.target); + switch(curr_tx_out_type){ case tx_out_type::out_cash: if(!token_seen && !advanced_seen) tx_type = tx_out_type::out_cash; @@ -682,8 +683,8 @@ namespace cryptonote } break; default: - if(get_tx_out_type(it.target) >= tx_out_type::out_advanced && get_tx_out_type(it.target) < tx_out_type::out_invalid - && ((tx_type < get_tx_out_type(it.target) && tx_type != tx_out_type::out_safex_purchase) || get_tx_out_type(it.target) == tx_out_type::out_safex_purchase + if(curr_tx_out_type >= tx_out_type::out_advanced && curr_tx_out_type < tx_out_type::out_invalid + && ((tx_type < curr_tx_out_type && tx_type != tx_out_type::out_safex_purchase) || curr_tx_out_type == tx_out_type::out_safex_purchase || tx_type == tx_out_type::out_invalid)){ tx_type = get_tx_out_type(it.target); advanced_seen = true; From 2a890cdf406e5c43672162da3e77002ed7f5ddbb Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Mon, 1 Jun 2020 12:53:26 +0200 Subject: [PATCH 18/24] Allow txin_to_script only in tx version 2 --- src/cryptonote_basic/cryptonote_format_utils.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index ae2f046dc..3baeb598a 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -680,10 +680,17 @@ namespace cryptonote { for(const auto& in: tx.vin) { - CHECK_AND_ASSERT_MES((in.type() == typeid(txin_to_script)) || (in.type() == typeid(txin_to_key)) - || (in.type() == typeid(txin_token_migration)) || (in.type() == typeid(txin_token_to_key)), - false, "wrong variant type: " << in.type().name() << ", expected " << typeid(txin_to_key).name() << ", in transaction id=" << get_transaction_hash(tx)); - + if (tx.version == 1) { + CHECK_AND_ASSERT_MES((in.type() == typeid(txin_to_key)) + || (in.type() == typeid(txin_token_migration)) || (in.type() == typeid(txin_token_to_key)), + false, "wrong variant type: " << in.type().name() << ", expected " << typeid(txin_to_key).name() << ", in transaction id=" << get_transaction_hash(tx)); + } else if (tx.version == 2) { + CHECK_AND_ASSERT_MES((in.type() == typeid(txin_to_script)) || (in.type() == typeid(txin_to_key)) + || (in.type() == typeid(txin_token_migration)) || (in.type() == typeid(txin_token_to_key)), + false, "wrong variant type: " << in.type().name() << ", expected " << typeid(txin_to_key).name() + << " or " << typeid(txin_token_to_key) << " or " << typeid(txin_token_migration) + << " or " << typeid(txin_to_script) << ", in transaction id=" << get_transaction_hash(tx)); + } } return true; } From 0ccde7be35542604c9285836010571803f1eecfb Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Mon, 1 Jun 2020 14:28:17 +0200 Subject: [PATCH 19/24] Small fix for compilation to pass --- src/cryptonote_basic/cryptonote_format_utils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 3baeb598a..3477883cd 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -688,8 +688,8 @@ namespace cryptonote CHECK_AND_ASSERT_MES((in.type() == typeid(txin_to_script)) || (in.type() == typeid(txin_to_key)) || (in.type() == typeid(txin_token_migration)) || (in.type() == typeid(txin_token_to_key)), false, "wrong variant type: " << in.type().name() << ", expected " << typeid(txin_to_key).name() - << " or " << typeid(txin_token_to_key) << " or " << typeid(txin_token_migration) - << " or " << typeid(txin_to_script) << ", in transaction id=" << get_transaction_hash(tx)); + << " or " << typeid(txin_token_to_key).name() << " or " << typeid(txin_token_migration).name() + << " or " << typeid(txin_to_script).name() << ", in transaction id=" << get_transaction_hash(tx)); } } return true; From 35d3989093386c5043aa8af5a970b35716101778 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Mon, 1 Jun 2020 14:46:50 +0200 Subject: [PATCH 20/24] Limit advanced_oputputs to 1 (unless tx is purchase or unstake) --- src/cryptonote_core/blockchain.cpp | 45 ++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 93145f560..366658222 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -3024,7 +3024,7 @@ bool Blockchain::check_safex_tx(const transaction &tx, tx_verification_context & if (tx.version == 1) return true; std::vector input_commands_to_execute; - std::set input_commands_to_check; + safex::command_t input_command_to_check; bool only_donate_seen = true; bool only_stake_seen = true; @@ -3042,7 +3042,7 @@ bool Blockchain::check_safex_tx(const transaction &tx, tx_verification_context & only_stake_seen = false; input_commands_to_execute.push_back(txin_script); - input_commands_to_check.insert(txin_script.command_type); + input_command_to_check = txin_script.command_type; } } @@ -3055,6 +3055,38 @@ bool Blockchain::check_safex_tx(const transaction &tx, tx_verification_context & return false; } + + std::vector advanced_outputs; + bool network_fee_out = false; + bool purchase_out = false; + bool feedback_token_out = false; + + for (auto txout: tx.vout) + { + if ((txout.target.type() == typeid(txout_to_script))) + { + auto txout_type = get_tx_out_type(txout.target); + advanced_outputs.push_back(txout_type); + if(txout_type == cryptonote::tx_out_type::out_safex_purchase) + purchase_out = true; + if(txout_type == cryptonote::tx_out_type::out_safex_feedback_token) + feedback_token_out = true; + if(txout_type == cryptonote::tx_out_type::out_network_fee) + network_fee_out = true; + } + } + + // Per TX there can be : + // * 1 advanced output for all types + // * 3 outputs if tx is safex_purchase + // * 0 outputs if tx is token_unstake + if (!(advanced_outputs.size() == 1 + || (advanced_outputs.size() == 3 && network_fee_out && purchase_out && feedback_token_out) + || (advanced_outputs.size() == 0 && input_command_to_check== safex::command_t::token_unstake))) { + tvc.m_safex_invalid_command = true; + return false; + } + //validate all command logic for (const txin_to_script cmd: input_commands_to_execute) if (!safex::validate_safex_command(*m_db, cmd)) { @@ -3063,12 +3095,9 @@ bool Blockchain::check_safex_tx(const transaction &tx, tx_verification_context & } //check all commands tx restrictions - for (const safex::command_t cmd_type: input_commands_to_check){ - if (!check_safex_tx_command(tx, cmd_type)){ - tvc.m_safex_invalid_input = true; - return false; - } - + if (!check_safex_tx_command(tx, input_command_to_check)){ + tvc.m_safex_invalid_input = true; + return false; } return true; From 17985d14dc5e692ff5e76c6fb236f468d269de45 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Mon, 1 Jun 2020 16:58:53 +0200 Subject: [PATCH 21/24] Check that every command input has a matching output --- src/cryptonote_core/blockchain.cpp | 33 +++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 366658222..d77898092 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -3200,7 +3200,7 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm } /* Check if donated cash amount matches */ - if (outputs_donated_cash_amount >= input_cash_amount) + if (outputs_donated_cash_amount >= input_cash_amount || outputs_donated_cash_amount == 0) { MERROR("Invalid safex cash input amount"); return false; @@ -3282,6 +3282,11 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm } + if(!create_account_seen){ + MERROR("Create account output not found"); + return false; + } + if(total_locked_tokens < SAFEX_CREATE_ACCOUNT_TOKEN_LOCK_FEE){ MERROR("Not enough tokens given as output. Needed: " + std::to_string(SAFEX_CREATE_ACCOUNT_TOKEN_LOCK_FEE) + ", actual sent: "+std::to_string(total_locked_tokens) ); return false; @@ -3351,6 +3356,11 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm } } } + + if(!edit_account_seen){ + MERROR("Edit account output not found"); + return false; + } } else if (command_type == safex::command_t::create_offer) { @@ -3417,6 +3427,11 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm } } } + + if(!create_offer_seen){ + MERROR("Create offer output not found"); + return false; + } } else if (command_type == safex::command_t::edit_offer) { @@ -3481,6 +3496,10 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm } } } + if(!edit_offer_seen){ + MERROR("Edit offer output not found"); + return false; + } } else if (command_type == safex::command_t::simple_purchase) { @@ -3613,6 +3632,10 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm } } } + if(!feedback_seen){ + MERROR("Create feedback output not found"); + return false; + } } else if (command_type == safex::command_t::create_price_peg) { @@ -3685,6 +3708,10 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm } } } + if(!create_price_peg_seen){ + MERROR("Create price peg output not found"); + return false; + } } else if (command_type == safex::command_t::update_price_peg) { @@ -3726,6 +3753,10 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm } } + if(!update_price_peg_seen){ + MERROR("Update price peg output not found"); + return false; + } } else { From c8b527696791df6eba064df3bf1342bc5c7c5b32 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Mon, 1 Jun 2020 18:09:04 +0200 Subject: [PATCH 22/24] Fix for are_safex_tokens_unlocked --- src/cryptonote_core/blockchain.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index d77898092..de3224c7a 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -6627,7 +6627,7 @@ bool Blockchain::are_safex_tokens_unlocked(const std::vector &tx_vin) { { const txin_token_to_key &in = boost::get(txin); if(in.token_amount != SAFEX_CREATE_ACCOUNT_TOKEN_LOCK_FEE) - return true; + continue; const std::vector absolute = cryptonote::relative_output_offsets_to_absolute(in.key_offsets); // Now we search the offsets and find their txs @@ -6644,7 +6644,7 @@ bool Blockchain::are_safex_tokens_unlocked(const std::vector &tx_vin) { { const txin_to_script &in = boost::get(txin); if(in.token_amount != SAFEX_CREATE_ACCOUNT_TOKEN_LOCK_FEE) - return true; + continue; const std::vector absolute = cryptonote::relative_output_offsets_to_absolute(in.key_offsets); // Now we search the offsets and find their txs From 298c084a8a9e0d031ea5bef9ba556ce9a497acb6 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Mon, 1 Jun 2020 20:39:45 +0200 Subject: [PATCH 23/24] Create LockedTXN in tx_pool only when needed --- src/cryptonote_core/tx_pool.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 604569f93..df50ad4e1 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -1080,8 +1080,6 @@ namespace cryptonote CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL1(m_blockchain); - LockedTXN lock(m_blockchain); - for(auto& sorted_it : m_txs_by_fee_and_receive_time) { txpool_tx_meta_t meta; @@ -1112,6 +1110,7 @@ namespace cryptonote } if (memcmp(&original_meta, &meta, sizeof(meta))) { + LockedTXN lock(m_blockchain); try { m_blockchain.update_txpool_tx(sorted_it.second, meta); From 867506428f6953644d732524a66bb6c9da38cdd5 Mon Sep 17 00:00:00 2001 From: Igor Grkavac Date: Mon, 1 Jun 2020 23:23:36 +0200 Subject: [PATCH 24/24] Add testnet 6.7 configs --- src/checkpoints/checkpoints.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/checkpoints/checkpoints.cpp b/src/checkpoints/checkpoints.cpp index 69e791eaf..87bee2248 100644 --- a/src/checkpoints/checkpoints.cpp +++ b/src/checkpoints/checkpoints.cpp @@ -165,7 +165,7 @@ namespace cryptonote if (nettype == TESTNET) { ADD_CHECKPOINT(1, "753e1454ebc44ffb18d7b390f7393a66ce7f3a8aaaf1e4e857af9df4e80d5784"); - ADD_CHECKPOINT(100000,"e255e1515acb9cccca8ebe9ce57718726c27c6e647878e6a18879dd42bb28434"); + ADD_CHECKPOINT(100000,"94b27cd801da1cbbe886e5ac8e98d3147a555923050a526f0d4754ef31416d54"); return true; }