diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f55455d..af96caf1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,7 +103,7 @@ else() else() set(ARCH_FLAG "-march=${ARCH}") endif() - set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=deprecated-declarations -Wno-error=sign-compare -Wno-error=strict-aliasing -Wno-error=type-limits -Wno-unused-parameter -Wno-error=unused-variable -Wno-aggregate-return -Wno-comment") + set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=deprecated-declarations -Wno-error=sign-compare -Wno-error=strict-aliasing -Wno-error=type-limits -Wno-unused-parameter -Wno-error=unused-variable -Wno-aggregate-return -Wno-comment -Wno-unknown-pragmas -Wno-pragmas") # if(NOT APPLE) # set(WARNINGS "${WARNINGS} -Werror") # endif() @@ -135,7 +135,7 @@ else() else() set(APPLE_FLAG "") endif() - set(C_WARNINGS "-Waggregate-return -Wnested-externs -Wstrict-prototypes") + set(C_WARNINGS "-Waggregate-return -Wnested-externs -Wstrict-prototypes -Wno-comment") set(CXX_WARNINGS "-Wno-reorder -Wno-missing-field-initializers") try_compile(STATIC_ASSERT_RES "${CMAKE_CURRENT_BINARY_DIR}/static-assert" "${CMAKE_CURRENT_SOURCE_DIR}/utils/test-static-assert.c" COMPILE_DEFINITIONS "-std=c++14") if(STATIC_ASSERT_RES) diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h index 107238b8..c9a96148 100644 --- a/contrib/epee/include/misc_log_ex.h +++ b/contrib/epee/include/misc_log_ex.h @@ -1261,7 +1261,7 @@ namespace log_space enabled_channels_local.insert(ch_name); genabled_channels.swap(enabled_channels_local); #ifndef ANDROID_BUILD - std::cout << "log channel '" << ch_name << "' enabled" << std::endl; + //std::cout << "log channel '" << ch_name << "' enabled" << std::endl; #endif } diff --git a/contrib/epee/include/net/net_utils_base.h b/contrib/epee/include/net/net_utils_base.h index 1ef06777..8b474516 100644 --- a/contrib/epee/include/net/net_utils_base.h +++ b/contrib/epee/include/net/net_utils_base.h @@ -79,6 +79,8 @@ namespace net_utils m_started(time(NULL)) {} + connection_context_base(const connection_context_base& a) = default; + connection_context_base& operator=(const connection_context_base& a) { set_details(a.m_connection_id, a.m_remote_ip, a.m_remote_port, a.m_is_income); diff --git a/contrib/epee/include/warnings.h b/contrib/epee/include/warnings.h index bbdcd9fe..433372fc 100644 --- a/contrib/epee/include/warnings.h +++ b/contrib/epee/include/warnings.h @@ -12,9 +12,13 @@ #define DISABLE_GCC_WARNING(w) #define DISABLE_CLANG_WARNING(w) #define DISABLE_GCC_AND_CLANG_WARNING(w) +#define ATTRIBUTE_UNUSED #else + +#define ATTRIBUTE_UNUSED __attribute__((unused)) + #include #define PUSH_VS_WARNINGS diff --git a/contrib/tor-connect b/contrib/tor-connect index 2e7176dc..13f47143 160000 --- a/contrib/tor-connect +++ b/contrib/tor-connect @@ -1 +1 @@ -Subproject commit 2e7176dcea611c1933bec4133591e3f1885b8b37 +Subproject commit 13f47143c0dcb8c12cfa293efc9d6d57ad3d1e37 diff --git a/src/common/db_backend_lmdb.cpp b/src/common/db_backend_lmdb.cpp index 6dfb1eea..75e60ce4 100644 --- a/src/common/db_backend_lmdb.cpp +++ b/src/common/db_backend_lmdb.cpp @@ -291,6 +291,10 @@ namespace tools if (res == MDB_NOTFOUND) return false; + if (res != MDB_SUCCESS) + { + return false; + } CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_get, h: " << h << ", ks: " << ks); res_buff.assign((const char*)data.mv_data, data.mv_size); diff --git a/src/common/variant_helper.h b/src/common/variant_helper.h index f0439db2..7fcf996b 100644 --- a/src/common/variant_helper.h +++ b/src/common/variant_helper.h @@ -4,9 +4,9 @@ #pragma once -#define VARIANT_SWITCH_BEGIN(v_type_obj) {auto & local_reference_eokcmeokmeokcm = v_type_obj; if(false) {; -#define VARIANT_CASE_CONST(v_type, typed_name) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { const v_type& typed_name = boost::get(local_reference_eokcmeokmeokcm); -#define VARIANT_CASE(v_type, typed_name) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { v_type& typed_name = boost::get(local_reference_eokcmeokmeokcm); +#define VARIANT_SWITCH_BEGIN(v_type_obj) {auto & local_reference_eokcmeokmeokcm ATTRIBUTE_UNUSED = v_type_obj; if(false) {; +#define VARIANT_CASE_CONST(v_type, typed_name) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { const v_type& typed_name ATTRIBUTE_UNUSED = boost::get(local_reference_eokcmeokmeokcm); +#define VARIANT_CASE(v_type, typed_name) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { v_type& typed_name ATTRIBUTE_UNUSED = boost::get(local_reference_eokcmeokmeokcm); #define VARIANT_CASE_TV(v_type) VARIANT_CASE(v_type, tv) #define VARIANT_CASE_OTHER() } else { #define VARIANT_CASE_THROW_ON_OTHER() } else { ASSERT_MES_AND_THROW("Unknown type in switch statemet: " << local_reference_eokcmeokmeokcm.type().name()); diff --git a/src/crypto/bitcoin/sha256.cpp b/src/crypto/bitcoin/sha256.cpp index 56266951..20c994f3 100644 --- a/src/crypto/bitcoin/sha256.cpp +++ b/src/crypto/bitcoin/sha256.cpp @@ -7,7 +7,7 @@ #include #include - +#include "warnings.h" //#include #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) @@ -462,6 +462,9 @@ namespace TransformD64Type TransformD64_4way = nullptr; TransformD64Type TransformD64_8way = nullptr; + PUSH_GCC_WARNINGS + DISABLE_GCC_AND_CLANG_WARNING(unused-function) + bool SelfTest() { // Input state (equal to the initial SHA256 state) static const uint32_t init[8] = { @@ -626,7 +629,7 @@ std::string SHA256AutoDetect() assert(SelfTest()); return ret; } - +POP_GCC_WARNINGS ////// SHA-256 CSHA256::CSHA256() : bytes(0) diff --git a/src/crypto/clsag.cpp b/src/crypto/clsag.cpp index a1b28dcb..80eb7982 100644 --- a/src/crypto/clsag.cpp +++ b/src/crypto/clsag.cpp @@ -14,7 +14,7 @@ namespace crypto #define DBG_VAL_PRINT(x) (void(0)) // std::cout << #x ": " << x << std::endl #define DBG_PRINT(x) (void(0)) // std::cout << x << std::endl - static std::ostream &operator <<(std::ostream &o, const crypto::hash &v) { return o << pod_to_hex(v); } + //static std::ostream &operator <<(std::ostream &o, const crypto::hash &v) { return o << pod_to_hex(v); } bool generate_CLSAG_GG(const hash& m, const std::vector& ring, const point_t& pseudo_out_amount_commitment, const key_image& ki, const scalar_t& secret_x, const scalar_t& secret_f, uint64_t secret_index, CLSAG_GG_signature& sig) diff --git a/src/crypto/crypto-sugar.h b/src/crypto/crypto-sugar.h index 1f9733dd..7ebe078e 100644 --- a/src/crypto/crypto-sugar.h +++ b/src/crypto/crypto-sugar.h @@ -141,8 +141,7 @@ namespace crypto crypto::secret_key m_sk; }; - scalar_t() - {} + scalar_t() = default; // won't check scalar range validity (< L) scalar_t(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3) @@ -844,8 +843,11 @@ namespace crypto // zeroes all elements void zero() { + PUSH_GCC_WARNINGS + DISABLE_GCC_AND_CLANG_WARNING(class-memaccess) size_t size_bytes = sizeof(scalar_t) * size(); memset(data(), 0, size_bytes); + POP_GCC_WARNINGS } // invert all elements in-place efficiently: 4*N muptiplications + 1 inversion @@ -1157,6 +1159,15 @@ namespace crypto return hs_calculator.calc_hash(); } + static scalar_t hs(const char(&str32)[32], const crypto::key_derivation& derivation, uint64_t index) + { + hs_t hs_calculator(3); + hs_calculator.add_32_chars(str32); + hs_calculator.add_pub_key(reinterpret_cast(derivation)); + hs_calculator.add_scalar(index); + return hs_calculator.calc_hash(); + } + static point_t hp(const point_t& p) { point_t result; @@ -1195,7 +1206,6 @@ namespace crypto { // hs won't touch memory if size is 0, so it's safe return hash_helper_t::hs(data(), sizeof(scalar_t) * size()); - } - + } } // namespace crypto diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 3a65ae65..12c69b0f 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -59,6 +59,7 @@ using namespace currency; #define BLOCKCHAIN_STORAGE_CONTAINER_ADDR_TO_ALIAS "addr_to_alias" #define BLOCKCHAIN_STORAGE_CONTAINER_TX_FEE_MEDIAN "median_fee2" #define BLOCKCHAIN_STORAGE_CONTAINER_GINDEX_INCS "gindex_increments" +#define BLOCKCHAIN_STORAGE_CONTAINER_ASSETS "assets" #define BLOCKCHAIN_STORAGE_OPTIONS_ID_CURRENT_BLOCK_CUMUL_SZ_LIMIT 0 #define BLOCKCHAIN_STORAGE_OPTIONS_ID_CURRENT_PRUNED_RS_HEIGHT 1 @@ -95,6 +96,7 @@ blockchain_storage::blockchain_storage(tx_memory_pool& tx_pool) :m_db(nullptr, m m_db_multisig_outs(m_db), m_db_solo_options(m_db), m_db_aliases(m_db), + m_db_assets(m_db), m_db_addr_to_alias(m_db), m_read_lock(m_rw_lock), m_db_current_block_cumul_sz_limit(BLOCKCHAIN_STORAGE_OPTIONS_ID_CURRENT_BLOCK_CUMUL_SZ_LIMIT, m_db_solo_options), @@ -279,6 +281,8 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); res = m_db_aliases.init(BLOCKCHAIN_STORAGE_CONTAINER_ALIASES); CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); + res = m_db_assets.init(BLOCKCHAIN_STORAGE_CONTAINER_ASSETS); + CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); res = m_db_addr_to_alias.init(BLOCKCHAIN_STORAGE_CONTAINER_ADDR_TO_ALIAS); CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); res = m_db_per_block_gindex_incs.init(BLOCKCHAIN_STORAGE_CONTAINER_GINDEX_INCS); @@ -297,6 +301,7 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro m_db_multisig_outs.set_cache_size(cache_size); m_db_solo_options.set_cache_size(cache_size); m_db_aliases.set_cache_size(cache_size); + m_db_assets.set_cache_size(cache_size); m_db_addr_to_alias.set_cache_size(cache_size); } @@ -414,6 +419,7 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro m_db_multisig_outs.deinit(); m_db_solo_options.deinit(); m_db_aliases.deinit(); + m_db_assets.deinit(); m_db_addr_to_alias.deinit(); m_db_per_block_gindex_incs.deinit(); m_db.close(); @@ -660,6 +666,7 @@ bool blockchain_storage::clear() m_db_outputs.clear(); m_db_multisig_outs.clear(); m_db_aliases.clear(); + m_db_assets.clear(); m_db_addr_to_alias.clear(); m_db_per_block_gindex_incs.clear(); m_pos_targetdata_cache.clear(); @@ -1549,6 +1556,7 @@ void blockchain_storage::reset_db_cache() const m_db_solo_options.clear_cache(); m_db_multisig_outs.clear_cache(); m_db_aliases.clear_cache(); + m_db_assets.clear_cache(); m_db_addr_to_alias.clear_cache(); } @@ -2949,6 +2957,7 @@ void blockchain_storage::print_db_cache_perfeormance_data() const DB_CONTAINER_PERF_DATA_ENTRY(m_db_multisig_outs) << ENDL DB_CONTAINER_PERF_DATA_ENTRY(m_db_solo_options) << ENDL DB_CONTAINER_PERF_DATA_ENTRY(m_db_aliases) << ENDL + DB_CONTAINER_PERF_DATA_ENTRY(m_db_assets) << ENDL DB_CONTAINER_PERF_DATA_ENTRY(m_db_addr_to_alias) << ENDL //DB_CONTAINER_PERF_DATA_ENTRY(m_db_per_block_gindex_incs) << ENDL //DB_CONTAINER_PERF_DATA_ENTRY(m_tx_fee_median) << ENDL @@ -3490,6 +3499,22 @@ bool blockchain_storage::unprocess_blockchain_tx_extra(const transaction& tx) r = pop_alias_info(ei.m_alias); CHECK_AND_ASSERT_MES(r, false, "failed to pop_alias_info"); } + + if (ei.m_asset_operation.operation_type != ASSET_DESCRIPTOR_OPERATION_UNDEFINED) + { + crypto::hash asset_id = currency::null_hash; + if (ei.m_asset_operation.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER) + { + asset_id = get_asset_id_from_descriptor(ei.m_asset_operation.descriptor); + } + else + { + CHECK_AND_ASSERT_MES(ei.m_asset_operation.asset_id.size() == 1, false, "Unexpected asset_id in operation"); + asset_id = ei.m_asset_operation.asset_id.back(); + } + r = pop_asset_info(asset_id); + CHECK_AND_ASSERT_MES(r, false, "failed to pop_alias_info"); + } return true; } //------------------------------------------------------------------ @@ -3514,6 +3539,27 @@ uint64_t blockchain_storage::get_aliases_count() const return m_db_aliases.size(); } //------------------------------------------------------------------ +bool blockchain_storage::get_asset_info(const crypto::hash& asset_id, asset_descriptor_base& info)const +{ + CRITICAL_REGION_LOCAL(m_read_lock); + auto as_ptr = m_db_assets.find(asset_id); + if (as_ptr) + { + if (as_ptr->size()) + { + info = as_ptr->back().descriptor; + return true; + } + } + return false; +} +//------------------------------------------------------------------ +uint64_t blockchain_storage::get_assets_count() const +{ + CRITICAL_REGION_LOCAL(m_read_lock); + return m_db_assets.size(); +} +//------------------------------------------------------------------ std::string blockchain_storage::get_alias_by_address(const account_public_address& addr)const { auto alias_ptr = m_db_addr_to_alias.find(addr); @@ -3696,6 +3742,48 @@ bool blockchain_storage::put_alias_info(const transaction & tx, extra_alias_entr return true; } //------------------------------------------------------------------ +bool blockchain_storage::pop_asset_info(const crypto::hash& asset_id) +{ + CRITICAL_REGION_LOCAL(m_read_lock); + + auto asset_history_ptr = m_db_assets.find(asset_id); + CHECK_AND_ASSERT_MES(asset_history_ptr && asset_history_ptr->size(), false, "empty name list in pop_asset_info"); + + assets_container::t_value_type local_asset_hist = *asset_history_ptr; + local_asset_hist.pop_back(); + if (local_asset_hist.size()) + m_db_assets.set(asset_id, local_asset_hist); + else + m_db_assets.erase(asset_id); + + LOG_PRINT_MAGENTA("[ASSET_POP]: " << asset_id << ": " << (!local_asset_hist.empty() ? "(prev)" : "(erased)"), LOG_LEVEL_1); + return true; +} +//------------------------------------------------------------------ +bool blockchain_storage::put_asset_info(const transaction & tx, asset_descriptor_operation & ado) +{ + CRITICAL_REGION_LOCAL(m_read_lock); + if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER) + { + crypto::hash asset_id = get_asset_id_from_descriptor(ado.descriptor); + auto asset_history_ptr = m_db_assets.find(asset_id); + CHECK_AND_ASSERT_MES(!asset_history_ptr, false, "Asset id already existing"); + assets_container::t_value_type local_asset_history = AUTO_VAL_INIT(local_asset_history); + local_asset_history.push_back(ado); + m_db_assets.set(asset_id, local_asset_history); + LOG_PRINT_MAGENTA("[ASSET_REGISTERED]: " << asset_id << ": " << ado.descriptor.full_name, LOG_LEVEL_1); + //TODO: + //rise_core_event(CORE_EVENT_ADD_ASSET, alias_info_to_rpc_alias_info(ai)); + } + else + { + //TODO: implement other operations + CHECK_AND_ASSERT_THROW(false, "not implemented yet"); + } + + return true; +} +//------------------------------------------------------------------ void blockchain_storage::set_event_handler(i_core_event_handler* event_handler) const { if (event_handler == nullptr) @@ -3785,6 +3873,12 @@ bool blockchain_storage::process_blockchain_tx_extra(const transaction& tx) r = put_alias_info(tx, ei.m_alias); CHECK_AND_ASSERT_MES(r, false, "failed to put_alias_info"); } + if (ei.m_asset_operation.operation_type != ASSET_DESCRIPTOR_OPERATION_UNDEFINED) + { + r = put_asset_info(tx, ei.m_asset_operation); + CHECK_AND_ASSERT_MES(r, false, "failed to put_asset_info"); + } + return true; } //------------------------------------------------------------------ diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index b8eab01e..8916d8f0 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -288,6 +288,8 @@ namespace currency uint64_t get_aliases_count()const; uint64_t get_block_h_older_then(uint64_t timestamp) const; bool validate_tx_service_attachmens_in_services(const tx_service_attachment& a, size_t i, const transaction& tx)const; + bool get_asset_info(const crypto::hash& asset_id, asset_descriptor_base& info)const; + uint64_t get_assets_count() const; bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const; bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const; bool check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const; @@ -486,6 +488,9 @@ namespace currency typedef tools::db::cached_key_value_accessor multisig_outs_container;// ms out id => ms_output_entry typedef tools::db::cached_key_value_accessor solo_options_container; typedef tools::db::basic_key_value_accessor per_block_gindex_increments_container; // height => [(amount, gindex_increment), ...] + + typedef tools::db::cached_key_value_accessor, true, false> assets_container; + //----------------------------------------- @@ -527,6 +532,7 @@ namespace currency address_to_aliases_container m_db_addr_to_alias; per_block_gindex_increments_container m_db_per_block_gindex_incs; + assets_container m_db_assets; @@ -645,6 +651,8 @@ namespace currency bool unprocess_blockchain_tx_attachments(const transaction& tx, uint64_t h, uint64_t timestamp); bool pop_alias_info(const extra_alias_entry& ai); bool put_alias_info(const transaction& tx, extra_alias_entry& ai); + bool pop_asset_info(const crypto::hash& asset_id); + bool put_asset_info(const transaction & tx, asset_descriptor_operation & ado); void fill_addr_to_alias_dict(); //bool resync_spent_tx_flags(); bool prune_ring_signatures_and_attachments_if_need(); diff --git a/src/currency_core/crypto_config.h b/src/currency_core/crypto_config.h index 0ca586cf..3e4deffe 100644 --- a/src/currency_core/crypto_config.h +++ b/src/currency_core/crypto_config.h @@ -6,6 +6,7 @@ // hash domain separation strings, 32 bytes long (31 chars + \0) // + #define CRYPTO_HDS_OUT_AMOUNT_MASK "ZANO_HDS_OUT_AMOUNT_MASK_______" #define CRYPTO_HDS_OUT_BLINDING_MASK "ZANO_HDS_OUT_BLINDING_MASK_____" #define CRYPTO_HDS_OUT_CONCEALING_POINT "ZANO_HDS_OUT_CONCEALING_POINT__" @@ -23,3 +24,6 @@ #define CRYPTO_HDS_ZARCANUM_LAST_POW_HASH "ZANO_HDS_ZARCANUM_LAST_POW_HASH" #define CRYPTO_HDS_ZARCANUM_SECRET_Q "ZANO_HDS_ZARCANUM_SECRET_Q_____" #define CRYPTO_HDS_ZARCANUM_PROOF_HASH "ZANO_HDS_ZARCANUM_PROOF_HASH___" + +#define CRYPTO_HDS_ASSET_CONTROL_KEY "ZANO_HDS_ASSET_CONTROL_KEY_____" +#define CRYPTO_HDS_ASSET_ID "ZANO_HDS_ASSET_ID______________" diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h index b25d4900..6dad210d 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -54,6 +54,8 @@ namespace currency const static crypto::key_derivation null_derivation = AUTO_VAL_INIT(null_derivation); const static crypto::hash gdefault_genesis = epee::string_tools::hex_to_pod("CC608F59F8080E2FBFE3C8C80EB6E6A953D47CF2D6AEBD345BADA3A1CAB99852"); + const static crypto::hash ffff_hash = epee::string_tools::hex_to_pod("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + typedef std::string payment_id_t; @@ -411,6 +413,7 @@ namespace currency FIELD(amount_commitment) FIELD(encrypted_amount) FIELD(mix_attr) + FIELD(etc_details) END_SERIALIZE() BEGIN_BOOST_SERIALIZATION() @@ -419,6 +422,7 @@ namespace currency BOOST_SERIALIZE(amount_commitment) BOOST_SERIALIZE(encrypted_amount) BOOST_SERIALIZE(mix_attr) + BOOST_SERIALIZE(etc_details) END_BOOST_SERIALIZATION() }; @@ -440,7 +444,7 @@ namespace currency struct zc_outs_range_proof { crypto::bpp_signature_serialized bpp; - uint8_t outputs_count; // how many outputs are included in the proof + uint8_t outputs_count = 0; // how many outputs are included in the proof BEGIN_SERIALIZE_OBJECT() FIELD(bpp) @@ -456,7 +460,7 @@ namespace currency // Zarcanum-aware CLSAG signature struct ZC_sig { - crypto::public_key pseudo_out_amount_commitment; // premultiplied by 1/8 + crypto::public_key pseudo_out_amount_commitment = null_pkey; // premultiplied by 1/8 crypto::CLSAG_GG_signature_serialized clsags_gg; BEGIN_SERIALIZE_OBJECT() @@ -472,7 +476,7 @@ namespace currency struct zc_balance_proof { - crypto::signature s; + crypto::signature s = null_sig; BEGIN_SERIALIZE_OBJECT() FIELD(s) @@ -704,6 +708,68 @@ namespace currency + struct asset_descriptor_base + { + uint64_t total_max_supply = 0; + uint64_t current_supply = 0; + uint8_t decimal_point = 12; + std::string ticker; + std::string full_name; + crypto::public_key owner = currency::null_pkey; + + BEGIN_VERSIONED_SERIALIZE() + FIELD(total_max_supply) + FIELD(current_supply) + FIELD(decimal_point) + FIELD(ticker) + FIELD(full_name) + FIELD(owner) + END_SERIALIZE() + + + BEGIN_BOOST_SERIALIZATION() + BOOST_SERIALIZE(total_max_supply) + BOOST_SERIALIZE(current_supply) + BOOST_SERIALIZE(decimal_point) + BOOST_SERIALIZE(ticker) + BOOST_SERIALIZE(full_name) + BOOST_SERIALIZE(owner) + END_BOOST_SERIALIZATION() + }; + + +#define ASSET_DESCRIPTOR_OPERATION_UNDEFINED 0 +#define ASSET_DESCRIPTOR_OPERATION_REGISTER 1 +#define ASSET_DESCRIPTOR_OPERATION_EMMIT 2 +#define ASSET_DESCRIPTOR_OPERATION_UPDATE 3 + + + struct asset_descriptor_operation + { + uint8_t operation_type = ASSET_DESCRIPTOR_OPERATION_UNDEFINED; + std::vector proof; + asset_descriptor_base descriptor; + std::vector asset_id; //questionable regarding form of optional fields + + + BEGIN_VERSIONED_SERIALIZE() + FIELD(operation_type) + FIELD(proof) + FIELD(descriptor) + FIELD(asset_id) + END_SERIALIZE() + + + BEGIN_BOOST_SERIALIZATION() + BOOST_SERIALIZE(operation_type) + BOOST_SERIALIZE(proof) + BOOST_SERIALIZE(descriptor) + END_BOOST_SERIALIZATION() + }; + + + + struct extra_padding { std::vector buff; //stub @@ -768,10 +834,10 @@ namespace currency END_SERIALIZE() }; - typedef boost::mpl::vector24< + typedef boost::mpl::vector25< tx_service_attachment, tx_comment, tx_payer_old, tx_receiver_old, tx_derivation_hint, std::string, tx_crypto_checksum, etc_tx_time, etc_tx_details_unlock_time, etc_tx_details_expiration_time, etc_tx_details_flags, crypto::public_key, extra_attachment_info, extra_alias_entry_old, extra_user_data, extra_padding, etc_tx_flags16_t, etc_tx_details_unlock_time2, - tx_payer, tx_receiver, extra_alias_entry, zarcanum_tx_data_v1, zc_outs_range_proof, zc_balance_proof + tx_payer, tx_receiver, extra_alias_entry, zarcanum_tx_data_v1, zc_outs_range_proof, zc_balance_proof, asset_descriptor_operation > all_payload_types; typedef boost::make_variant_over::type payload_items_v; @@ -1099,6 +1165,9 @@ SET_VARIANT_TAGS(currency::zc_balance_proof, 47, "zc_balance_proof"); SET_VARIANT_TAGS(currency::open_asset_id, 48, "asset_id"); +SET_VARIANT_TAGS(currency::asset_descriptor_operation, 48, "asset_descriptor_base"); + + #undef SET_VARIANT_TAGS diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index eb2b5186..ebe69442 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -232,7 +232,7 @@ #define BC_OFFERS_CURRENCY_MARKET_FILENAME "market.bin" #ifndef TESTNET -#define WALLET_FILE_SERIALIZATION_VERSION 153 +#define WALLET_FILE_SERIALIZATION_VERSION 154 #else #define WALLET_FILE_SERIALIZATION_VERSION (CURRENCY_FORMATION_VERSION+69) #endif diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index b9ff5de5..95eaec9e 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -335,8 +335,16 @@ namespace currency { if (tx.version > TRANSACTION_VERSION_PRE_HF4) { + //@#@ TODO: This is just a temporary code + uint64_t assets_emmited = 0; + asset_descriptor_operation ado = AUTO_VAL_INIT(ado); + if (get_type_in_variant_container(tx.extra, ado) && ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER) + { + assets_emmited += ado.descriptor.current_supply; + } + size_t zc_inputs_count = 0; - uint64_t bare_inputs_sum = additional_inputs_amount_and_fees_for_mining_tx; + uint64_t bare_inputs_sum = additional_inputs_amount_and_fees_for_mining_tx + assets_emmited; for(auto& vin : tx.vin) { VARIANT_SWITCH_BEGIN(vin); @@ -655,19 +663,18 @@ namespace currency //--------------------------------------------------------------- struct tx_extra_handler : public boost::static_visitor { - mutable bool was_padding; //let the padding goes only at the end - mutable bool was_pubkey; - mutable bool was_attachment; - mutable bool was_userdata; - mutable bool was_alias; + mutable bool was_padding = false; //let the padding goes only at the end + mutable bool was_pubkey = false; + mutable bool was_attachment = false; + mutable bool was_userdata = false; + mutable bool was_alias = false; + mutable bool was_asset = false; tx_extra_info& rei; const transaction& rtx; tx_extra_handler(tx_extra_info& ei, const transaction& tx) :rei(ei), rtx(tx) - { - was_padding = was_pubkey = was_attachment = was_userdata = was_alias = false; - } + {} #define ENSURE_ONETIME(varname, entry_name) CHECK_AND_ASSERT_MES(varname == false, false, "double entry in tx_extra: " entry_name); varname = true; @@ -690,6 +697,12 @@ namespace currency rei.m_alias = ae; return true; } + bool operator()(const asset_descriptor_operation & ado) const + { + ENSURE_ONETIME(was_asset, "asset"); + rei.m_asset_operation = ado; + return true; + } bool operator()(const extra_alias_entry_old& ae) const { return operator()(static_cast(ae)); @@ -791,6 +804,17 @@ namespace currency return derive_public_key_from_target_address(destination_addr, tx_sec_key, index, out_eph_public_key, derivation); } //--------------------------------------------------------------- + bool derive_key_pair_from_key_pair(const crypto::public_key& src_pub_key, const crypto::secret_key& src_sec_key, crypto::secret_key& derived_sec_key, crypto::public_key& derived_pub_key, const char(&hs_domain)[32], uint64_t index) + { + crypto::key_derivation derivation = AUTO_VAL_INIT(derivation); + bool r = crypto::generate_key_derivation(src_pub_key, src_sec_key, derivation); + CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << src_pub_key << ", " << src_sec_key << ")"); + crypto::scalar_t sec_key = crypto::hash_helper_t::hs(hs_domain, derivation, index); + derived_sec_key = sec_key.as_secret_key(); + derived_pub_key = (sec_key * crypto::c_point_G).to_public_key(); + return true; + } + //--------------------------------------------------------------- // derivation = 8 * tx_sec_key * destination_addr.view_public_key // out_eph_public_key = destination_addr.spend_public_key + Hs(derivation, index) * G bool derive_public_key_from_target_address(const account_public_address& destination_addr, const crypto::secret_key& tx_sec_key, size_t index, crypto::public_key& out_eph_public_key, crypto::key_derivation& derivation) @@ -1554,7 +1578,6 @@ namespace currency ftp.tx_outs_attr = tx_outs_attr; ftp.shuffle = shuffle; ftp.flags = flags; - ftp.tx_version; finalized_tx ft = AUTO_VAL_INIT(ft); ft.tx = tx; @@ -1685,6 +1708,13 @@ namespace currency return true; } + + crypto::hash get_asset_id_from_descriptor(const asset_descriptor_base& adb) + { + return get_hash_from_POD_objects(CRYPTO_HDS_ASSET_ID, adb.owner); + } + + bool construct_tx(const account_keys& sender_account_keys, const finalize_tx_param& ftp, finalized_tx& result) { const std::vector& sources = ftp.sources; @@ -1705,8 +1735,6 @@ namespace currency result.ftp = ftp; CHECK_AND_ASSERT_MES(destinations.size() <= CURRENCY_TX_MAX_ALLOWED_OUTS, false, "Too many outs (" << destinations.size() << ")! Tx can't be constructed."); - bool watch_only_mode = sender_account_keys.spend_secret_key == null_skey; - bool append_mode = false; if (flags&TX_FLAG_SIGNATURE_MODE_SEPARATE && tx.vin.size()) append_mode = true; @@ -1768,10 +1796,23 @@ namespace currency tx.extra.insert(tx.extra.end(), extra_local.begin(), extra_local.end()); } -// //first: separate zarcanum inputs and regular one - //std::vector zc_sources; - //std::vector NLSAG_sources; + uint64_t summary_inputs_money = 0; + + crypto::hash asset_id_for_destinations = currency::null_hash; + asset_descriptor_operation* pado = nullptr; + if (tx.version > TRANSACTION_VERSION_PRE_HF4) + { + pado = get_type_in_variant_container(tx.extra); + if (pado) + { + crypto::secret_key stub = AUTO_VAL_INIT(stub); + bool r = derive_key_pair_from_key_pair(sender_account_keys.account_address.spend_public_key, one_time_secret_key, stub, pado->descriptor.owner, CRYPTO_HDS_ASSET_CONTROL_KEY); + CHECK_AND_ASSERT_MES(r, false, "Failed to derive_public_key_from_tx_and_account_pub_key()"); + //also assign this asset id to destinations + asset_id_for_destinations = get_asset_id_from_descriptor(pado->descriptor); + } + } std::vector in_contexts; @@ -1782,12 +1823,12 @@ namespace currency size_t current_index = 0; inputs_mapping.resize(sources.size()); size_t input_starter_index = tx.vin.size(); - uint64_t summary_inputs_money = 0; bool has_zc_inputs = false; //fill inputs NLSAG and Zarcanum for (const tx_source_entry& src_entr : sources) { - inputs_mapping[current_index] = current_index++; + inputs_mapping[current_index] = current_index; + current_index++; in_contexts.push_back(input_generation_context_data()); if(src_entr.is_multisig()) {//multisig input @@ -1901,9 +1942,27 @@ namespace currency { tx.vin.push_back(ins_zc); }*/ + uint64_t amount_of_assets = 0; + std::vector shuffled_dsts(destinations); + if (asset_id_for_destinations != currency::null_hash) + { + //must be asset publication + for (auto& item : shuffled_dsts) + { + if (item.asset_id == currency::ffff_hash) + { + item.asset_id = asset_id_for_destinations; + amount_of_assets += item.amount; + } + } + CHECK_AND_ASSERT_MES(pado, false, "pado is null ??"); + pado->descriptor.current_supply = amount_of_assets; + //TODO: temporary + summary_inputs_money += amount_of_assets; + } + // "Shuffle" outs - std::vector shuffled_dsts(destinations); if (shuffle) std::sort(shuffled_dsts.begin(), shuffled_dsts.end(), [](const tx_destination_entry& de1, const tx_destination_entry& de2) { return de1.amount < de2.amount; }); @@ -1984,7 +2043,7 @@ namespace currency if (!has_zc_inputs) { - r = generate_tx_balance_proof(tx, blinding_masks_sum); + r = generate_tx_balance_proof(tx, blinding_masks_sum, amount_of_assets); CHECK_AND_ASSERT_MES(r, false, "generate_tx_balance_proof failed"); } } @@ -2010,8 +2069,6 @@ namespace currency if (tx.attachment.size()) add_attachments_info_to_extra(tx.extra, tx.attachment); } - - // // generate ring signatures // @@ -2021,10 +2078,12 @@ namespace currency //size_t in_context_index = 0; crypto::scalar_t local_blinding_masks_sum = 0; // ZC only r = false; - for (size_t i = 0; i != sources.size(); i++) + for (size_t i_ = 0; i_ != sources.size(); i_++) { - const tx_source_entry& source_entry = sources[inputs_mapping[i]]; - crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, i + input_starter_index, tx_prefix_hash); + size_t i_mapped = inputs_mapping[i_]; + + const tx_source_entry& source_entry = sources[i_mapped]; + crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, i_ + input_starter_index, tx_prefix_hash); CHECK_AND_ASSERT_MES(tx_hash_for_signature != null_hash, false, "prepare_prefix_hash_for_sign failed"); std::stringstream ss_ring_s; @@ -2032,14 +2091,14 @@ namespace currency { // ZC // blinding_masks_sum is supposed to be sum(mask of all tx output) - sum(masks of all pseudo out commitments) - r = generate_ZC_sig(tx_hash_for_signature, i + input_starter_index, source_entry, in_contexts[i], sender_account_keys, blinding_masks_sum, flags, - local_blinding_masks_sum, tx, i + 1 == sources.size()); + r = generate_ZC_sig(tx_hash_for_signature, i_ + input_starter_index, source_entry, in_contexts[i_mapped], sender_account_keys, blinding_masks_sum, flags, + local_blinding_masks_sum, tx, i_ + 1 == sources.size()); CHECK_AND_ASSERT_MES(r, false, "generate_ZC_sigs failed"); } else { // NLSAG - r = generate_NLSAG_sig(tx_hash_for_signature, tx_prefix_hash, i + input_starter_index, source_entry, sender_account_keys, in_contexts[i], txkey, flags, tx, &ss_ring_s); + r = generate_NLSAG_sig(tx_hash_for_signature, tx_prefix_hash, i_ + input_starter_index, source_entry, sender_account_keys, in_contexts[i_mapped], txkey, flags, tx, &ss_ring_s); CHECK_AND_ASSERT_MES(r, false, "generate_NLSAG_sig failed"); } @@ -3324,6 +3383,12 @@ namespace currency tv.type = "zc_balance_proof"; return true; } + template + bool operator()(const t_type& t_t) + { + tv.type = typeid(t_t).name(); + return true; + } }; //------------------------------------------------------------------ template diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index 9849d678..1fcf9107 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -71,6 +71,7 @@ namespace currency extra_alias_entry m_alias; std::string m_user_data_blob; extra_attachment_info m_attachment_info; + asset_descriptor_operation m_asset_operation; }; //--------------------------------------------------------------------------------------------------------------- @@ -289,6 +290,7 @@ namespace currency uint64_t get_tx_version(uint64_t h, const hard_forks_descriptor& hfd); bool construct_tx(const account_keys& sender_account_keys, const finalize_tx_param& param, finalized_tx& result); + crypto::hash get_asset_id_from_descriptor(const asset_descriptor_base& adb); bool sign_multisig_input_in_tx(currency::transaction& tx, size_t ms_input_index, const currency::account_keys& keys, const currency::transaction& source_tx, bool *p_is_input_fully_signed = nullptr); @@ -316,6 +318,8 @@ namespace currency bool generate_key_image_helper(const account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki); bool derive_public_key_from_target_address(const account_public_address& destination_addr, const crypto::secret_key& tx_sec_key, size_t index, crypto::public_key& out_eph_public_key, crypto::key_derivation& derivation); bool derive_public_key_from_target_address(const account_public_address& destination_addr, const crypto::secret_key& tx_sec_key, size_t index, crypto::public_key& out_eph_public_key); + bool derive_key_pair_from_key_pair(const crypto::public_key& src_pub_key, const crypto::secret_key& src_sec_key, crypto::secret_key& derived_sec_key, crypto::public_key& derived_pub_key, const char(&hs_domain)[32], uint64_t index = 0); + std::string short_hash_str(const crypto::hash& h); bool is_mixattr_applicable_for_fake_outs_counter(uint8_t mix_attr, uint64_t fake_attr_count); bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t current_blockchain_size, uint64_t current_time); @@ -537,6 +541,13 @@ namespace currency return print_fixed_decimal_point(amount, CURRENCY_DISPLAY_DECIMAL_POINT); } //--------------------------------------------------------------- + + template + std::string print_asset_money(t_number amount, size_t decimal_point) + { + return print_fixed_decimal_point(amount, decimal_point); + } + //--------------------------------------------------------------- template bool alias_rpc_details_to_alias_info(const alias_rpc_details_t& ard, currency::extra_alias_entry& ai) { diff --git a/src/currency_core/currency_format_utils_abstract.h b/src/currency_core/currency_format_utils_abstract.h index d08f266f..3d8b4226 100644 --- a/src/currency_core/currency_format_utils_abstract.h +++ b/src/currency_core/currency_format_utils_abstract.h @@ -91,22 +91,46 @@ namespace currency ++result; } return result; - } + } //--------------------------------------------------------------- template - bool get_type_in_variant_container(variant_t_container& av, specific_type_t& a) + specific_type_t* get_type_in_variant_container(variant_t_container& av) { for (auto& ai : av) { if (ai.type() == typeid(specific_type_t)) { - a = boost::get(ai); - return true; + return &boost::get(ai); } } + return nullptr; + } + //--------------------------------------------------------------- + template + bool get_type_in_variant_container(variant_t_container& av, specific_type_t& a) + { + const specific_type_t* pa = get_type_in_variant_container(av); + if (pa) + { + a = *pa; + return true; + } return false; } //--------------------------------------------------------------- + //--------------------------------------------------------------- + template + specific_type_t& get_type_in_variant_container_by_ref(variant_t_container& av) + { + for (auto& ai : av) + { + if (ai.type() == typeid(specific_type_t)) + { + return boost::get(ai); + } + } + ASSERT_MES_AND_THROW("Objec not found"); + } // if cb returns true, it means "continue", false -- means "stop" template bool process_type_in_variant_container(const variant_container_t& av, callback_t& cb, bool return_value_if_none_found = true) @@ -194,6 +218,7 @@ namespace currency catch(...) { // should never go here, just precaution + return false; } return false; @@ -423,6 +448,26 @@ namespace currency size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size); + inline + void put_t_to_buff(std::string& buff) + {} + + template + void put_t_to_buff(std::string& buff, const T& var1, Types&... var2) + { + static_assert(std::is_pod::value, "T must be a POD type."); + buff.append((const char*)&var1, sizeof(var1)); + put_t_to_buff(buff, var2...); + } + + template + crypto::hash get_hash_from_POD_objects(Types&... var1) + { + std::string buff; + put_t_to_buff(buff, var1...); + return crypto::cn_fast_hash(buff.data(), buff.size()); + } + #define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \ CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \ diff --git a/src/currency_core/currency_format_utils_transactions.h b/src/currency_core/currency_format_utils_transactions.h index 0c8a9e8c..c38c9cc4 100644 --- a/src/currency_core/currency_format_utils_transactions.h +++ b/src/currency_core/currency_format_utils_transactions.h @@ -100,8 +100,11 @@ namespace currency tx_destination_entry() = default; tx_destination_entry(uint64_t a, const account_public_address& ad) : amount(a), addr(1, ad) {} + tx_destination_entry(uint64_t a, const account_public_address& ad, const crypto::hash& aid) : amount(a), addr(1, ad), asset_id(aid) {} tx_destination_entry(uint64_t a, const account_public_address& ad, uint64_t ut) : amount(a), addr(1, ad), unlock_time(ut) {} - tx_destination_entry(uint64_t a, const std::list& addr) : amount(a), addr(addr), minimum_sigs(addr.size()) {} + tx_destination_entry(uint64_t a, const std::list& addr) : amount(a), addr(addr), minimum_sigs(addr.size()){} + tx_destination_entry(uint64_t a, const std::list& addr, const crypto::hash& aid) : amount(a), addr(addr), minimum_sigs(addr.size()), asset_id(aid) {} + BEGIN_SERIALIZE_OBJECT() FIELD(amount) @@ -110,6 +113,7 @@ namespace currency FIELD(amount_to_provide) FIELD(unlock_time) FIELD(htlc_options) + FIELD(asset_id) END_SERIALIZE() }; diff --git a/src/currency_core/dispatch_core_events.h b/src/currency_core/dispatch_core_events.h index dadff8b1..19d3df40 100644 --- a/src/currency_core/dispatch_core_events.h +++ b/src/currency_core/dispatch_core_events.h @@ -17,6 +17,7 @@ #define CORE_EVENT_ADD_ALIAS "CORE_EVENT_ADD_ALIAS" #define CORE_EVENT_UPDATE_ALIAS "CORE_EVENT_UPDATE_ALIAS" #define CORE_EVENT_BLOCK_ADDED "CORE_EVENT_BLOCK_ADDED" +#define CORE_EVENT_ADD_ASSET "CORE_EVENT_ADD_ASSET" namespace currency diff --git a/src/currency_core/offers_service_basics.h b/src/currency_core/offers_service_basics.h index 809bf88b..1dffe367 100644 --- a/src/currency_core/offers_service_basics.h +++ b/src/currency_core/offers_service_basics.h @@ -19,9 +19,9 @@ namespace bc_services { //fields filled in UI - uint8_t offer_type; // OFFER_TYPE_PRIMARY_TO_TARGET(SELL ORDER) - 0, OFFER_TYPE_TARGET_TO_PRIMARY(BUY ORDER) - 1 etc. - uint64_t amount_primary; // amount of the currency - uint64_t amount_target; // amount of other currency or goods + uint8_t offer_type = 0; // OFFER_TYPE_PRIMARY_TO_TARGET(SELL ORDER) - 0, OFFER_TYPE_TARGET_TO_PRIMARY(BUY ORDER) - 1 etc. + uint64_t amount_primary = 0; // amount of the currency + uint64_t amount_target = 0; // amount of other currency or goods std::string bonus; // std::string target; // [] currency / goods std::string primary; // currency for goods @@ -33,7 +33,7 @@ namespace bc_services std::string deal_option; // []full amount, by parts std::string category; // [] std::string preview_url; // [] - uint8_t expiration_time; // n-days + uint8_t expiration_time = 0; // n-days //----------------- BEGIN_KV_SERIALIZE_MAP() diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h index b3b54e23..5b5383b1 100644 --- a/src/serialization/serialization.h +++ b/src/serialization/serialization.h @@ -61,7 +61,7 @@ inline bool do_serialize(Archive &ar, T &v) #define VARIANT_TAG(A, T, Tg) \ template struct variant_serialization_traits, T> { static inline typename A::variant_tag_type get_tag() { return Tg; } } #define BEGIN_SERIALIZE() \ - template class Archive> bool do_serialize(Archive &_ser_ar) { + template class Archive> bool do_serialize(Archive &_ser_ar) {uint8_t s_current_version ATTRIBUTE_UNUSED = 0; uint8_t s_version ATTRIBUTE_UNUSED = 0; #define BEGIN_SERIALIZE_OBJECT() \ template class Archive> bool do_serialize(Archive &_ser_ar) { _ser_ar.begin_object(); bool _ser_res = do_serialize_object(_ser_ar); _ser_ar.end_object(); return _ser_res; } \ template class Archive> bool do_serialize_object(Archive &_ser_ar){ @@ -98,6 +98,28 @@ do { \ if (!_ser_ar.stream().good()) return false; \ } while (0); +#define VERSION() \ +do { \ + _ser_ar.tag("VERSION"); \ + if (!_ser_ar.stream().good()){break;} \ + _ser_ar.serialize_varint(s_version); \ + if (!_ser_ar.stream().good()) return false; \ + if(s_version > s_current_version) return false; \ +} while (0); + +#define CURRENT_VERSION(v) \ +do { \ + s_current_version = v; \ + if (_ser_ar.is_saving_arch()) { s_version = v; } \ +} while (0); + + + +#define BEGIN_VERSIONED_SERIALIZE() \ + BEGIN_SERIALIZE() \ + VERSION() + + #define DEFINE_SERIALIZATION_VERSION(v) inline static uint32_t get_serialization_version() { return v; } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 1147660a..468c15e5 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -752,6 +752,49 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t } } + if (ptc.tx_money_spent_in_ins) + { + //check if there are asset_registration that belong to this wallet + asset_descriptor_operation ado = AUTO_VAL_INIT(ado); + if (get_type_in_variant_container(tx.extra, ado)) + { + if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER) + { + crypto::public_key self_check = AUTO_VAL_INIT(self_check); + crypto::secret_key asset_control_key = AUTO_VAL_INIT(asset_control_key); + bool r = derive_key_pair_from_key_pair(tx_pub_key, m_account.get_keys().spend_secret_key, asset_control_key, self_check, CRYPTO_HDS_ASSET_CONTROL_KEY); + if (!r) + { + //not critical error, continue to work + LOG_ERROR("Failed to derive_key_pair_from_key_pair for asset_descriptor_operation in tx " << get_transaction_hash(tx)); + }else + { + if (self_check != ado.descriptor.owner) + { + //still not critical error + LOG_ERROR("Public key from asset_descriptor_operation(" << ado.descriptor.owner << ") not much with derived public key(" << self_check << "), for tx" << get_transaction_hash(tx)); + } + else + { + wallet_own_asset_context& asset_context = m_own_asset_descriptors[get_hash_from_POD_objects(CRYPTO_HDS_ASSET_ID, ado.descriptor.owner)]; + asset_context.asset_descriptor = ado.descriptor; + asset_context.height = height; + std::stringstream ss; + ss << "New Asset Registered:" + << ENDL << "Name: " << asset_context.asset_descriptor.full_name + << ENDL << "Ticker: " << asset_context.asset_descriptor.ticker + << ENDL << "Total Max Supply: " << print_asset_money(asset_context.asset_descriptor.total_max_supply, asset_context.asset_descriptor.decimal_point) + << ENDL << "Current Supply: " << print_asset_money(asset_context.asset_descriptor.current_supply, asset_context.asset_descriptor.decimal_point) + << ENDL << "DecimalPoint: " << asset_context.asset_descriptor.decimal_point; + + WLT_LOG_MAGENTA(ss.str(), LOG_LEVEL_0); + if (m_wcallback) + m_wcallback->on_message(i_wallet2_callback::ms_yellow, ss.str()); + } + } + } + } + } if (ptc.tx_money_spent_in_ins) {//this actually is transfer transaction, notify about spend @@ -1834,7 +1877,7 @@ detail::split_strategy_id_t wallet2::get_current_split_strategy() return tools::detail::ssi_void; } // -void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx) +void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx, const crypto::hash& asset_id) { std::vector extra; std::vector attachments; @@ -1843,13 +1886,14 @@ void wallet2::transfer(uint64_t amount, const currency::account_public_address& dst.resize(1); dst.back().addr.push_back(acc); dst.back().amount = amount; + dst.back().asset_id = asset_id; this->transfer(dst, 0, 0, TX_DEFAULT_FEE, extra, attachments, get_current_split_strategy(), tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD), result_tx); } //---------------------------------------------------------------------------------------------------- -void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc) +void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc, const crypto::hash& asset_id) { transaction result_tx = AUTO_VAL_INIT(result_tx); - this->transfer(amount, acc, result_tx); + this->transfer(amount, acc, result_tx, asset_id); } //---------------------------------------------------------------------------------------------------- void wallet2::reset_creation_time(uint64_t timestamp) @@ -2507,6 +2551,15 @@ void wallet2::detach_blockchain(uint64_t including_height) ++it; } + //asset descriptors + for (auto it = m_own_asset_descriptors.begin(); it != m_own_asset_descriptors.end(); ) + { + if (including_height <= it->second.height) + it = m_own_asset_descriptors.erase(it); + else + ++it; + } + WLT_LOG_L0("Detached blockchain on height " << including_height << ", transfers detached " << transfers_detached << ", blocks detached " << blocks_detached); } //---------------------------------------------------------------------------------------------------- @@ -4122,6 +4175,25 @@ void wallet2::request_alias_registration(currency::extra_alias_entry& ai, curren transfer(destinations, 0, 0, fee, extra, attachments, get_current_split_strategy(), tx_dust_policy(DEFAULT_DUST_THRESHOLD), res_tx, CURRENCY_TO_KEY_OUT_RELAXED, false); } //---------------------------------------------------------------------------------------------------- +void wallet2::publish_new_asset(const currency::asset_descriptor_base& asset_info, const std::vector& destinations, currency::transaction& result_tx, crypto::hash& asset_id) +{ + asset_descriptor_operation asset_reg_info = AUTO_VAL_INIT(asset_reg_info); + asset_reg_info.descriptor = asset_info; + asset_reg_info.operation_type = ASSET_DESCRIPTOR_OPERATION_REGISTER; + construct_tx_param ctp = get_default_construct_tx_param(); + ctp.dsts = destinations; + ctp.extra.push_back(asset_reg_info); + + finalized_tx ft = AUTO_VAL_INIT(ft); + this->transfer(ctp, ft, true, nullptr); + result_tx = ft.tx; + //get generated asset id + currency::asset_descriptor_operation ado = AUTO_VAL_INIT(ado); + bool r = get_type_in_variant_container(result_tx.extra, ado); + CHECK_AND_ASSERT_THROW_MES(r, "Failed find asset info in tx"); + asset_id = get_asset_id_from_descriptor(ado.descriptor); +} +//---------------------------------------------------------------------------------------------------- void wallet2::request_alias_update(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward) { if (!validate_alias_name(ai.m_alias)) @@ -4930,6 +5002,9 @@ assets_selection_context wallet2::get_needed_money(uint64_t fee, const std::vect amounts_map[currency::null_hash].needed_amount = fee; for(auto& dt : dsts) { + if(dt.asset_id == currency::ffff_hash) + continue; //this destination for emmition only + THROW_IF_TRUE_WALLET_EX(0 == dt.amount, error::zero_destination); uint64_t money_to_add = dt.amount; if (dt.amount_to_provide) @@ -5591,22 +5666,20 @@ void wallet2::prepare_tx_destinations(uint64_t needed_money, change_dts.asset_id = asset_id; } WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(found_money >= needed_money, "needed_money==" << needed_money << " < found_money==" << found_money); - + if (asset_id != currency::null_hash) + { + if (change_dts.amount) + { + final_detinations.push_back(change_dts); + } + return; + } uint64_t dust = 0; bool r = detail::apply_split_strategy_by_id(destination_split_strategy_id, dsts, change_dts, dust_policy.dust_threshold, final_detinations, dust, WALLET_MAX_ALLOWED_OUTPUT_AMOUNT); WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(r, "invalid split strategy id: " << destination_split_strategy_id); WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(dust_policy.dust_threshold >= dust, "invalid dust value: dust = " << dust << ", dust_threshold = " << dust_policy.dust_threshold); - //@#@ -#ifdef _DEBUG - if (final_detinations.size() > 10) - { - WLT_LOG_L0("final_detinations.size()=" << final_detinations.size()); - } -#endif - //@#@ - if (0 != dust && !dust_policy.add_to_fee) { final_detinations.push_back(currency::tx_destination_entry(dust, dust_policy.addr_for_dust)); @@ -5666,6 +5739,7 @@ void wallet2::prepare_transaction(construct_tx_param& ctp, currency::finalize_tx prepare_tx_destinations(needed_money_map, static_cast(ctp.split_strategy_id), ctp.dust_policy, ctp.dsts, ftp.prepared_destinations); TIME_MEASURE_FINISH_MS(prepare_tx_destinations_time); + if (ctp.mark_tx_as_complete && !ftp.sources.empty()) ftp.sources.back().separately_signed_tx_complete = true; @@ -5806,10 +5880,9 @@ construct_tx_param wallet2::get_default_construct_tx_param_inital() ctp.shuffle = 0; return ctp; } -const construct_tx_param& wallet2::get_default_construct_tx_param() +construct_tx_param wallet2::get_default_construct_tx_param() { - static construct_tx_param ctp = get_default_construct_tx_param_inital(); - return ctp; + return get_default_construct_tx_param_inital(); } //---------------------------------------------------------------------------------------------------- bool wallet2::store_unsigned_tx_to_file_and_reserve_transfers(const currency::finalize_tx_param& ftp, const std::string& filename, std::string* p_unsigned_tx_blob_str /* = nullptr */) diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index d655e511..a630312e 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -184,8 +184,8 @@ namespace tools else { currency::decompose_amount_into_digits(de.amount, dust_threshold, - [&](uint64_t chunk) { splitted_dsts.push_back(currency::tx_destination_entry(chunk, de.addr)); }, - [&](uint64_t a_dust) { splitted_dsts.push_back(currency::tx_destination_entry(a_dust, de.addr)); }, max_output_allowed); + [&](uint64_t chunk) { splitted_dsts.push_back(currency::tx_destination_entry(chunk, de.addr, de.asset_id)); }, + [&](uint64_t a_dust) { splitted_dsts.push_back(currency::tx_destination_entry(a_dust, de.addr, de.asset_id)); }, max_output_allowed); } } @@ -241,7 +241,7 @@ namespace tools const currency::tx_destination_entry& change_dst, uint64_t dust_threshold, std::vector& splitted_dsts, uint64_t& dust, uint64_t max_output_allowed) { - splitted_dsts = dsts; + splitted_dsts.insert(splitted_dsts.end(), dsts.begin(), dsts.end()); if (change_dst.amount > 0) splitted_dsts.push_back(change_dst); } @@ -252,6 +252,9 @@ namespace tools const currency::tx_destination_entry& change_dst, uint64_t dust_threshold, std::vector& splitted_dsts, uint64_t& dust, uint64_t max_output_allowed) { + //&&&&& + LOG_PRINT_MAGENTA("[--apply_split_strategy_by_id, split strtegy_id: " << id, LOG_LEVEL_0); + switch (id) { case ssi_digit: @@ -506,6 +509,19 @@ namespace tools }; + struct wallet_own_asset_context + { + currency::asset_descriptor_base asset_descriptor; + crypto::secret_key control_key; + uint64_t height = 0; + + BEGIN_BOOST_SERIALIZATION() + BOOST_SERIALIZE(asset_descriptor) + BOOST_SERIALIZE(control_key) + BOOST_SERIALIZE(height) + END_BOOST_SERIALIZATION() + }; + void assign_account(const currency::account_base& acc); void generate(const std::wstring& path, const std::string& password, bool auditable_wallet); void restore(const std::wstring& path, const std::string& pass, const std::string& seed_or_tracking_seed, bool tracking_wallet, const std::string& seed_password); @@ -551,7 +567,8 @@ namespace tools void request_alias_registration(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward, const crypto::secret_key& authority_key = currency::null_skey); void request_alias_update(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward); bool check_available_sources(std::list& amounts); - + + void publish_new_asset(const currency::asset_descriptor_base& asset_info, const std::vector& destinations, currency::transaction& result_tx, crypto::hash& asset_id); bool set_core_proxy(const std::shared_ptr& proxy); void set_pos_mint_packing_size(uint64_t new_size); @@ -564,8 +581,8 @@ namespace tools uint64_t unlocked_balance() const; - void transfer(uint64_t amount, const currency::account_public_address& acc); - void transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx); + void transfer(uint64_t amount, const currency::account_public_address& acc, const crypto::hash& asset_id = currency::null_hash); + void transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx, const crypto::hash& asset_id = currency::null_hash); void transfer(const std::vector& dsts, size_t fake_outputs_count, @@ -803,6 +820,10 @@ namespace tools a & m_active_htlcs; a & m_active_htlcs_txid; + if (ver < 154) + return; + + a & m_own_asset_descriptors; } void wipeout_extra_if_needed(std::vector& transfer_history); @@ -985,7 +1006,7 @@ private: template bool process_input_t(const input_t& in_t, wallet2::process_transaction_context& ptc, const currency::transaction& tx); - const construct_tx_param& get_default_construct_tx_param(); + construct_tx_param get_default_construct_tx_param(); uint64_t get_tx_expiration_median() const; @@ -1080,6 +1101,7 @@ private: std::unordered_map m_unconfirmed_txs; std::unordered_set m_unconfirmed_multisig_transfers; std::unordered_map m_tx_keys; + std::unordered_map m_own_asset_descriptors; std::multimap m_htlcs; //map [expired_if_more_then] -> height of expiration amount_gindex_to_transfer_id_container m_active_htlcs; // map [amount; gindex] -> transfer index @@ -1111,6 +1133,7 @@ private: } // namespace tools BOOST_CLASS_VERSION(tools::wallet2, WALLET_FILE_SERIALIZATION_VERSION) + BOOST_CLASS_VERSION(tools::wallet_public::wallet_transfer_info, 11) BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 3) BOOST_CLASS_VERSION(tools::wallet2::transfer_details_base, 2) @@ -1288,7 +1311,7 @@ namespace tools ptc.is_derived_from_coinbase = true; else ptc.is_derived_from_coinbase = false; - WLT_LOG_L0("Spent key out, transfer #" << tr_index << ", amount: " << print_money(td.amount()) << ", with tx: " << get_transaction_hash(tx) << ", at height " << ptc.height << + WLT_LOG_L0("Spent key out, transfer #" << tr_index << ", amount: " << currency::print_money(td.amount()) << ", with tx: " << get_transaction_hash(tx) << ", at height " << ptc.height << "; flags: " << flags_before << " -> " << td.m_flags); ptc.mtd.spent_indices.push_back(ptc.i); remove_transfer_from_expiration_list(tr_index); diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index 8c820551..e45eafb6 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -463,6 +463,7 @@ namespace tools ss << currency::get_account_address_as_str(a) << ";"; } ss << " anount: " << currency::print_money(dst.amount); + ss << " asset_id: " << dst.asset_id; } ss << "\nunlock_time: " << m_unlock_time; @@ -757,4 +758,5 @@ if (cond) ss << mess; \ LOG_ERROR("THROW EXCEPTION: wallet_common_error"); \ tools::error::throw_wallet_ex(std::string(__FILE__ ":" STRINGIZE(__LINE__)), ss.str()); \ - } \ No newline at end of file + } + diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 55c0cfa9..897d9a4b 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -1001,7 +1001,6 @@ bool init_output_indices(map_output_idx_t& outs, map_output_t& outs_mine, const { for (const block& blk : blockchain) { - volatile uint64_t height = get_block_height(blk); std::vector vtx; vtx.push_back(&blk.miner_tx); diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 12a0de86..b0638233 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -912,7 +912,7 @@ int main(int argc, char* argv[]) // GENERATE_AND_PLAY(pos_wallet_minting_same_amount_diff_outs); // Long test! Takes ~10 hours to simulate 6000 blocks on 2015 middle-end computer //GENERATE_AND_PLAY(pos_emission_test); // Long test! by demand only GENERATE_AND_PLAY(pos_wallet_big_block_test); - GENERATE_AND_PLAY(block_template_against_txs_size); + //GENERATE_AND_PLAY(block_template_against_txs_size); // Long test! by demand only GENERATE_AND_PLAY(pos_altblocks_validation); // alternative blocks and generic chain-switching tests @@ -1060,6 +1060,14 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(isolate_auditable_and_proof); GENERATE_AND_PLAY(zarcanum_basic_test); + + //stop_on_first_fail = true; + //for (size_t i = 0; i != 100; i++) + //{ + multiassets_basic_test::ts_starter = 0; + GENERATE_AND_PLAY(multiassets_basic_test); + //} + // GENERATE_AND_PLAY(gen_block_reward); diff --git a/tests/core_tests/chaingen_pch.cpp b/tests/core_tests/chaingen_pch.cpp index 11878762..4f86d7c7 100644 --- a/tests/core_tests/chaingen_pch.cpp +++ b/tests/core_tests/chaingen_pch.cpp @@ -1,5 +1,4 @@ // Copyright (c) 2022 Zano Project // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#pragma once #include "chaingen.h" diff --git a/tests/core_tests/chaingen_tests_list.h b/tests/core_tests/chaingen_tests_list.h index c4eac1be..cf3fbb7d 100644 --- a/tests/core_tests/chaingen_tests_list.h +++ b/tests/core_tests/chaingen_tests_list.h @@ -41,3 +41,4 @@ #include "atomic_tests.h" #include "isolate_auditable_and_proof.h" #include "zarcanum_test.h" +#include "multiassets_test.h" diff --git a/tests/core_tests/checkpoints_tests.cpp b/tests/core_tests/checkpoints_tests.cpp index 918615c9..3e7b0b76 100644 --- a/tests/core_tests/checkpoints_tests.cpp +++ b/tests/core_tests/checkpoints_tests.cpp @@ -927,7 +927,7 @@ bool gen_checkpoints_set_after_switching_to_altchain::generate(std::vector& events) const REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); m_alice_bob_start_amount = MK_TEST_COINS(200); - uint64_t amount_chunks = 10; + //uint64_t amount_chunks = 10; m_alice_bob_start_chunk_amount = m_alice_bob_start_amount / 10; transaction tx_0 = AUTO_VAL_INIT(tx_0); @@ -3159,7 +3159,7 @@ bool escrow_balance::generate(std::vector& events) const bool escrow_balance::c1(currency::core& c, size_t ev_index, const std::vector& events) { - bool r = false, stub_bool = false; + bool r = false; CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count()); std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]); diff --git a/tests/core_tests/hard_fork_1.cpp b/tests/core_tests/hard_fork_1.cpp index ab49fb94..9134c831 100644 --- a/tests/core_tests/hard_fork_1.cpp +++ b/tests/core_tests/hard_fork_1.cpp @@ -186,7 +186,7 @@ bool hard_fork_1_unlock_time_2_in_coinbase::generate(std::vector& { // Test idea: make sure chain switches without PoS before and after hardfork - bool r = false; + //bool r = false; GENERATE_ACCOUNT(miner_acc); GENERATE_ACCOUNT(alice_acc); MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time()); diff --git a/tests/core_tests/hard_fork_2.cpp b/tests/core_tests/hard_fork_2.cpp index fbe68459..5935968a 100644 --- a/tests/core_tests/hard_fork_2.cpp +++ b/tests/core_tests/hard_fork_2.cpp @@ -76,7 +76,7 @@ bool hard_fork_2_tx_payer_in_wallet::generate(std::vector& eve bool hard_fork_2_tx_payer_in_wallet::c1(currency::core& c, size_t ev_index, const std::vector& events) { - bool r = false, stub_bool = false; + bool r = false; CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count()); std::shared_ptr miner_wlt = init_playtime_test_wallet(events, c, m_accounts[MINER_ACC_IDX]); std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]); @@ -324,7 +324,7 @@ bool hard_fork_2_tx_receiver_in_wallet::generate(std::vector& bool hard_fork_2_tx_receiver_in_wallet::c1(currency::core& c, size_t ev_index, const std::vector& events) { - bool r = false, stub_bool = false; + bool r = false; CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count()); std::shared_ptr miner_wlt = init_playtime_test_wallet(events, c, m_accounts[MINER_ACC_IDX]); std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]); @@ -468,7 +468,7 @@ bool hard_fork_2_tx_extra_alias_entry_in_wallet::generate(std::vector& events) { - bool r = false, stub_bool = false; + bool r = false; CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count()); std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]); std::shared_ptr miner_wlt = init_playtime_test_wallet(events, c, m_accounts[MINER_ACC_IDX]); @@ -670,7 +670,7 @@ bool hard_fork_2_auditable_addresses_basics::generate(std::vector& events) { - bool r = false, stub_bool = false; + bool r = false; CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count()); std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]); std::shared_ptr bob_wlt = init_playtime_test_wallet(events, c, m_accounts[BOB_ACC_IDX]); @@ -909,7 +909,7 @@ bool hard_fork_2_awo_wallets_basic_test::c1(currency::core& c, size static const std::wstring bob_wo_restored_filename(L"bob_wo_restored_wallet"); static const std::wstring bob_non_auditable_filename(L"bob_non_auditable_wallet"); - bool r = false, stub_bool = false; + bool r = false; CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count()); std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX); @@ -1181,7 +1181,7 @@ bool hard_fork_2_alias_update_using_old_tx::generate(std::vector bool hard_fork_2_alias_update_using_old_tx::c1(currency::core& c, size_t ev_index, const std::vector& events) { - bool r = false, stub_bool = false; + bool r = false; CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count()); std::shared_ptr miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX); diff --git a/tests/core_tests/multiassets_test.cpp b/tests/core_tests/multiassets_test.cpp new file mode 100644 index 00000000..8bc70f08 --- /dev/null +++ b/tests/core_tests/multiassets_test.cpp @@ -0,0 +1,148 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "chaingen.h" +#include "multiassets_test.h" +#include "wallet_test_core_proxy.h" + +#include "random_helper.h" + +#define AMOUNT_TO_TRANSFER_MULTIASSETS_BASIC (TESTS_DEFAULT_FEE) + +#define AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC 500000000000000000 + + + +using namespace currency; +uint64_t multiassets_basic_test::ts_starter = 0; +//------------------------------------------------------------------------------ +multiassets_basic_test::multiassets_basic_test() +{ + // TODO: remove the following line + + LOG_PRINT_MAGENTA("STARTER TS: " << ts_starter, LOG_LEVEL_0); + random_state_test_restorer::reset_random(ts_starter); + + REGISTER_CALLBACK_METHOD(multiassets_basic_test, configure_core); + REGISTER_CALLBACK_METHOD(multiassets_basic_test, c1); + + m_hardforks.set_hardfork_height(1, 1); + m_hardforks.set_hardfork_height(2, 1); + m_hardforks.set_hardfork_height(3, 1); + m_hardforks.set_hardfork_height(4, 1); +} + +bool multiassets_basic_test::generate(std::vector& events) const +{ + m_accounts.resize(MINER_ACC_IDX+1); + account_base& miner_acc = m_accounts[MINER_ACC_IDX]; + miner_acc.generate(); + + uint64_t ts = 145000000; + MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts); + DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks + set_hard_fork_heights_to_generator(generator); + //TODO: Need to make sure REWIND_BLOCKS_N and other coretests codebase are capable of following hardfork4 rules + //in this test hardfork4 moment moved to runtime section + REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3); + + DO_CALLBACK(events, "c1"); + + return true; +} + +bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::vector& events) +{ + bool r = false; + std::shared_ptr miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX); + miner_wlt->get_account().set_createtime(0); + account_base alice_acc; + alice_acc.generate(); + std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, alice_acc); + alice_wlt->get_account().set_createtime(0); + miner_wlt->refresh(); + + asset_descriptor_base adb = AUTO_VAL_INIT(adb); + adb.total_max_supply = 1000000000000000000; //1M coins + adb.full_name = "Test coins"; + adb.ticker = "TCT"; + adb.decimal_point = 12; + + std::vector destinations(2); + destinations[0].addr.push_back(miner_wlt->get_account().get_public_address()); + destinations[0].amount = AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC; + destinations[0].asset_id = currency::ffff_hash; + destinations[1].addr.push_back(alice_wlt->get_account().get_public_address()); + destinations[1].amount = AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC; + destinations[1].asset_id = currency::ffff_hash; + + LOG_PRINT_MAGENTA("destinations[0].asset_id:" << destinations[0].asset_id, LOG_LEVEL_0); + LOG_PRINT_MAGENTA("destinations[1].asset_id:" << destinations[1].asset_id, LOG_LEVEL_0); + LOG_PRINT_MAGENTA("currency::ffff_hash:" << currency::ffff_hash, LOG_LEVEL_0); + + currency::transaction tx = AUTO_VAL_INIT(tx); + crypto::hash asset_id = currency::null_hash; + miner_wlt->publish_new_asset(adb, destinations, tx, asset_id); + LOG_PRINT_L0("Published new asset: " << asset_id << ", tx_id: " << currency::get_transaction_hash(tx)); + + //pass over hardfork + r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed"); + + + miner_wlt->refresh(); + alice_wlt->refresh(); + uint64_t mined = 0; + std::unordered_map balances; + miner_wlt->balance(balances, mined); + + auto it_asset = balances.find(asset_id); + auto it_native = balances.find(currency::null_hash); + + + CHECK_AND_ASSERT_MES(it_asset != balances.end() && it_native != balances.end(), false, "Failed to find needed asset in result balances"); + CHECK_AND_ASSERT_MES(it_asset->second.total == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC, false, "Failed to find needed asset in result balances"); + CHECK_AND_ASSERT_MES(it_native->second.total == uint64_t(17517226)*COIN, false, "Failed to find needed asset in result balances"); + + + balances.clear(); + alice_wlt->balance(balances, mined); + + it_asset = balances.find(asset_id); + it_native = balances.find(currency::null_hash); + + CHECK_AND_ASSERT_MES(it_asset != balances.end(), false, "Failed to find needed asset in result balances"); + CHECK_AND_ASSERT_MES(it_native == balances.end(), false, "Failed to find needed asset in result balances"); + CHECK_AND_ASSERT_MES(it_asset->second.total == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC, false, "Failed to find needed asset in result balances"); + + miner_wlt->transfer(AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC/2, alice_wlt->get_account().get_public_address(), asset_id); + //pass over hardfork + r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed"); + + alice_wlt->refresh(); + balances.clear(); + alice_wlt->balance(balances, mined); + + it_asset = balances.find(asset_id); + + CHECK_AND_ASSERT_MES(it_asset != balances.end(), false, "Failed to find needed asset in result balances"); + CHECK_AND_ASSERT_MES(it_asset->second.total == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC + AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC/2, false, "Failed to find needed asset in result balances"); + + try { + + miner_wlt->transfer(AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC / 2, alice_wlt->get_account().get_public_address(), asset_id); + //pass over hardfork + CHECK_AND_ASSERT_MES(false, false, "Transfer with 0 Zano worked(fail)"); + } + catch (...) + { + return true; + } + + + + return true; +} diff --git a/tests/core_tests/multiassets_test.h b/tests/core_tests/multiassets_test.h new file mode 100644 index 00000000..74e17bf6 --- /dev/null +++ b/tests/core_tests/multiassets_test.h @@ -0,0 +1,18 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once +#include "chaingen.h" +#include "wallet_tests_basic.h" + + +struct multiassets_basic_test : public wallet_test +{ + static uint64_t ts_starter; + multiassets_basic_test(); + bool generate(std::vector& events) const; + bool c1(currency::core& c, size_t ev_index, const std::vector& events); +}; + diff --git a/tests/core_tests/wallet_tests.cpp b/tests/core_tests/wallet_tests.cpp index ae2620bc..3d891568 100644 --- a/tests/core_tests/wallet_tests.cpp +++ b/tests/core_tests/wallet_tests.cpp @@ -3290,7 +3290,6 @@ bool wallet_unconfimed_tx_balance::generate(std::vector& event bool wallet_unconfimed_tx_balance::c1(currency::core& c, size_t ev_index, const std::vector& events) { - bool r = false; std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX); CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt, MK_TEST_COINS(100), false, UINT64_MAX, MK_TEST_COINS(100)), false, ""); @@ -3505,7 +3504,6 @@ wallet_watch_only_and_chain_switch::wallet_watch_only_and_chain_switch() bool wallet_watch_only_and_chain_switch::generate(std::vector& events) const { - bool r = false; m_accounts.resize(TOTAL_ACCS_COUNT); account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); @@ -3602,7 +3600,6 @@ wallet_spend_form_auditable_and_track::wallet_spend_form_auditable_and_track() bool wallet_spend_form_auditable_and_track::generate(std::vector& events) const { - bool r = false; m_accounts.resize(TOTAL_ACCS_COUNT); account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); diff --git a/tests/core_tests/zarcanum_test.cpp b/tests/core_tests/zarcanum_test.cpp index 6da94f61..7ce373d5 100644 --- a/tests/core_tests/zarcanum_test.cpp +++ b/tests/core_tests/zarcanum_test.cpp @@ -86,7 +86,7 @@ bool zarcanum_basic_test::c1(currency::core& c, size_t ev_index, const std::vect //miner_wlt->refresh(); alice_wlt->refresh(); - uint64_t unlocked = 0; + //uint64_t unlocked = 0; //uint64_t balance = alice_wlt->balance(unlocked); CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", transfer_amount * 4, UINT64_MAX, transfer_amount * 4), false, ""); diff --git a/tests/unit_tests/proxy_to_coretests.cpp b/tests/unit_tests/proxy_to_coretests.cpp new file mode 100644 index 00000000..df09b253 --- /dev/null +++ b/tests/unit_tests/proxy_to_coretests.cpp @@ -0,0 +1,12 @@ +// Copyright (c) 2012-2022 The Zano project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "gtest/gtest.h" + +//#include "common/util.h" +//#include "p2p/net_peerlist.h" +//#include "core_tests/chaingen.h" + + +//TODO \ No newline at end of file diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp index e2aa25db..43df9c0e 100644 --- a/tests/unit_tests/serialization.cpp +++ b/tests/unit_tests/serialization.cpp @@ -740,3 +740,166 @@ TEST(Serialization, serializes_transacion_versions) validate_tx_serialisation(tx); } + +struct A +{ + std::string one; + std::string two; + std::vector vector_one; + + BEGIN_SERIALIZE() + FIELD(one) + FIELD(two) + FIELD(vector_one) + END_SERIALIZE() +}; + +struct A_v1 : public A +{ + std::vector vector_two; + + + BEGIN_SERIALIZE() + CURRENT_VERSION(1) + FIELD(one) + FIELD(two) + FIELD(vector_one) + VERSION() + if (s_version < 1) return true; + FIELD(vector_two) + END_SERIALIZE() +}; + +struct A_v2 : public A_v1 +{ + std::vector vector_3; + std::vector vector_4; + + + BEGIN_SERIALIZE() + CURRENT_VERSION(2) + FIELD(one) + FIELD(two) + FIELD(vector_one) + VERSION() + if (s_version < 1) return true; + FIELD(vector_two) + if (s_version < 2) return true; + FIELD(vector_3) + FIELD(vector_4) + END_SERIALIZE() +}; + +struct A_v3 : public A_v2 +{ + std::vector vector_5; + + BEGIN_SERIALIZE() + CURRENT_VERSION(3) + FIELD(one) + FIELD(two) + FIELD(vector_one) + VERSION() + if (s_version < 1) return true; + FIELD(vector_two) + if (s_version < 2) return true; + FIELD(vector_3) + FIELD(vector_4) + if (s_version < 3) return true; + FIELD(vector_5) + END_SERIALIZE() +}; + +inline bool operator==(const A& lhs, const A& rhs) +{ + if ((lhs.one != rhs.one || lhs.two != rhs.two || lhs.vector_one != rhs.vector_one)) + { + return false; + } + return true; +} + +inline bool operator==(const A_v1& lhs, const A_v1& rhs) +{ + if (!(static_cast(lhs) == static_cast(rhs))) + return false; + if ((lhs.vector_two != rhs.vector_two)) + { + return false; + } + return true; +} + +inline bool operator==(const A_v2& lhs, const A_v2& rhs) +{ + if (!(static_cast(lhs) == static_cast(rhs))) + return false; + if ((lhs.vector_3 != rhs.vector_3)) + { + return false; + } + return true; +} + +inline bool operator==(const A_v3& lhs, const A_v3& rhs) +{ + if (!(static_cast(lhs) == static_cast(rhs))) + return false; + if ((lhs.vector_5 != rhs.vector_5)) + { + return false; + } + return true; +} + +template +bool perform_test_ser_vers(second& f) +{ + string blob; + first s_s = AUTO_VAL_INIT(s_s); + if (!serialization::dump_binary(f, blob)) + return false; + if (!serialization::parse_binary(blob, s_s)) + return false; + + + if (!(f == static_cast(s_s))) + { + return false; + } + return true; +} + +TEST(Serialization, versioning2) +{ + A_v3 a_3; + a_3.one = "one"; + a_3.two = "two"; + a_3.vector_one.push_back(a_3.one); + a_3.vector_one.push_back(a_3.two); + a_3.vector_two = a_3.vector_one; + a_3.vector_5 = a_3.vector_4 = a_3.vector_3 = a_3.vector_two; + + A_v2 a_2(a_3); + A_v1 a_1(a_3); + A a(a_3); + + bool r = perform_test_ser_vers(a); + ASSERT_TRUE(r); + r = perform_test_ser_vers(a); + ASSERT_TRUE(r); + r = perform_test_ser_vers(a); + ASSERT_TRUE(r); + + r = perform_test_ser_vers(a_1); + ASSERT_TRUE(r); + r = perform_test_ser_vers(a_1); + ASSERT_TRUE(r); + + r = perform_test_ser_vers(a_2); + ASSERT_TRUE(r); + + r = perform_test_ser_vers(a_3); + ASSERT_TRUE(r); + +} \ No newline at end of file