diff --git a/src/crypto/crypto-sugar.h b/src/crypto/crypto-sugar.h index 280a8f79..3d2e0457 100644 --- a/src/crypto/crypto-sugar.h +++ b/src/crypto/crypto-sugar.h @@ -1153,6 +1153,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; diff --git a/src/currency_core/crypto_config.h b/src/currency_core/crypto_config.h index 06eaa3e8..4203f4bb 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__" @@ -22,3 +23,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_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 77f7dee9..1ed699e6 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -719,7 +719,8 @@ namespace currency #define ASSET_DESCRIPTOR_OPERATION_UNDEFINED 0 #define ASSET_DESCRIPTOR_OPERATION_REGISTER 1 -#define ASSET_DESCRIPTOR_OPERATION_UPDATE 2 +#define ASSET_DESCRIPTOR_OPERATION_EMMIT 2 +#define ASSET_DESCRIPTOR_OPERATION_UPDATE 3 struct asset_descriptor_operation @@ -810,7 +811,7 @@ 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, zarcanum_outs_range_proof, zc_balance_proof, asset_descriptor_operation diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index c6246d79..c87f8541 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -231,7 +231,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 3292ab8c..d6b870e1 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -807,6 +807,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::public_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 << ")"); + 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) @@ -1970,6 +1981,18 @@ namespace currency } } + + if (tx.version > TRANSACTION_VERSION_PRE_HF4) + { + asset_descriptor_operation ado = AUTO_VAL_INIT(ado); + if (get_type_in_variant_container(tx.extra, ado)) + { + 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, ado.descriptor.owner, CRYPTO_HDS_ASSET_CONTROL_KEY); + CHECK_AND_ASSERT_MES(r, false, "Failed to derive_public_key_from_tx_and_account_pub_key()"); + } + } + //sort inputs and mapping if it's zarcanum hardfork if (tx.version > TRANSACTION_VERSION_PRE_HF4) { @@ -3313,6 +3336,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 0e0da357..51cf782a 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -315,6 +315,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::public_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); @@ -536,6 +538,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/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index cf8ad1b7..51638b1e 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -752,6 +752,48 @@ 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[hash_helper_t::hs(CRYPTO_HDS_ASSET_ID, ado.descriptor.owner), 0]; + asset_context.asset_descriptor = ado.descriptor; + 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 @@ -4123,22 +4165,19 @@ 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 asset_descriptor_base& asset_info, const std::vector& destinations) +void wallet2::publish_new_asset(const asset_descriptor_base& asset_info/*, const std::vector& destinations*/, currency::transaction& result_tx) { 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); - std::vector destinations_local = destinations; - std::vector extra; - std::vector attachments; - - extra.push_back(asset_reg_info); - - 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); - - + finalized_tx ft = AUTO_VAL_INIT(ft); + this->transfer(ctp, ft, true, nullptr); + result_tx = ft.tx; } //---------------------------------------------------------------------------------------------------- void wallet2::request_alias_update(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward) diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index c6837a08..130b8ca3 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -506,6 +506,17 @@ namespace tools }; + struct wallet_own_asset_context + { + asset_descriptor_base asset_descriptor; + crypto::secret_key control_key; + + BEGIN_BOOST_SERIALIZATION() + BOOST_SERIALIZE(asset_descriptor) + BOOST_SERIALIZE(control_key) + 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); @@ -552,7 +563,7 @@ namespace tools 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 asset_descriptor_base& asset_info, const std::vector& destinations); + void publish_new_asset(const asset_descriptor_base& asset_info/*, const std::vector& destinations*/, currency::transaction& result_tx); bool set_core_proxy(const std::shared_ptr& proxy); void set_pos_mint_packing_size(uint64_t new_size); @@ -804,6 +815,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); @@ -1084,6 +1099,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 @@ -1115,6 +1131,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)