diff --git a/include/metaverse/blockchain/validate_transaction.hpp b/include/metaverse/blockchain/validate_transaction.hpp index fa25c689b..307e7903e 100644 --- a/include/metaverse/blockchain/validate_transaction.hpp +++ b/include/metaverse/blockchain/validate_transaction.hpp @@ -142,7 +142,9 @@ class BCB_API validate_transaction uint64_t value_in_; uint64_t asset_amount_in_; std::vector asset_certs_in_; - std::string old_symbol_in_; // used for check same asset/did/mit symbol in previous outputs + std::string old_asset_symbol_in_; // used for check same asset/did/mit symbol in previous outputs + std::string old_did_symbol_in_; + std::string old_mit_symbol_in_; std::string old_cert_symbol_in_; // used for check same cert symbol in previous outputs uint32_t current_input_; chain::point::indexes unconfirmed_; diff --git a/include/metaverse/explorer/extensions/base_helper.hpp b/include/metaverse/explorer/extensions/base_helper.hpp index 74eb90c5f..d5344e27b 100644 --- a/include/metaverse/explorer/extensions/base_helper.hpp +++ b/include/metaverse/explorer/extensions/base_helper.hpp @@ -302,7 +302,8 @@ class BCX_API base_transfer_common receiver_record::list&& receiver_list, uint64_t fee, std::string&& symbol, std::string&& from, std::string&& change, uint32_t locktime = 0, uint32_t sequence = bc::max_input_sequence, - exclude_range_t exclude_etp_range = {0, 0}) + exclude_range_t exclude_etp_range = {0, 0}, + std::set&& payment_domain_set = std::set()) : blockchain_{blockchain} , symbol_{std::move(symbol)} , from_{std::move(from)} @@ -312,6 +313,7 @@ class BCX_API base_transfer_common , locktime_(locktime) , sequence_(sequence) , exclude_etp_range_(exclude_etp_range) + , payment_domain_set_(std::move(payment_domain_set)) { }; @@ -392,6 +394,7 @@ class BCX_API base_transfer_common uint8_t unspent_did_{0}; uint8_t payment_mit_{0}; uint8_t unspent_mit_{0}; + std::set payment_domain_set_; std::vector receiver_list_; std::vector from_list_; uint32_t locktime_; @@ -410,10 +413,11 @@ class BCX_API base_transfer_helper : public base_transfer_common std::string&& change = std::string(""), uint32_t locktime = 0, uint32_t sequence = bc::max_input_sequence, - exclude_range_t exclude_etp_range = {0, 0}) + exclude_range_t exclude_etp_range = {0, 0}, + std::set&& payment_domain_set = std::set()) : base_transfer_common(blockchain, std::move(receiver_list), fee, std::move(symbol), std::move(from), - std::move(change), locktime, sequence, exclude_etp_range) + std::move(change), locktime, sequence, exclude_etp_range, std::move(payment_domain_set)) , cmd_{cmd} , name_{std::move(name)} , passwd_{std::move(passwd)} @@ -769,11 +773,12 @@ class BCX_API registering_mit : public base_transfer_helper registering_mit(command& cmd, bc::blockchain::block_chain_impl& blockchain, std::string&& name, std::string&& passwd, std::string&& from, std::string&& symbol, std::map&& mit_map, + std::set&& payment_domain_set, receiver_record::list&& receiver_list, uint64_t fee, uint32_t locktime = 0) : base_transfer_helper(cmd, blockchain, std::move(name), std::move(passwd), std::move(from), std::move(receiver_list), - fee, std::move(symbol), "", locktime) + fee, std::move(symbol), "", locktime, bc::max_input_sequence, {0,0}, std::move(payment_domain_set)) , mit_map_(mit_map) {} diff --git a/src/lib/blockchain/validate_transaction.cpp b/src/lib/blockchain/validate_transaction.cpp index 7798f1dae..a4e84e5e2 100644 --- a/src/lib/blockchain/validate_transaction.cpp +++ b/src/lib/blockchain/validate_transaction.cpp @@ -184,7 +184,11 @@ void validate_transaction::reset(uint64_t last_height) value_in_ = 0; asset_amount_in_ = 0; asset_certs_in_.clear(); - old_symbol_in_ = ""; + + old_asset_symbol_in_ = ""; + old_did_symbol_in_ = ""; + old_mit_symbol_in_ = ""; + old_cert_symbol_in_ = ""; } @@ -953,6 +957,7 @@ code validate_transaction::check_asset_mit_transaction() const std::string asset_address; uint64_t num_mit_transfer = 0; uint64_t num_mit_register = 0; + std::string cert_owner; for (auto& output : tx.outputs) { if (output.is_asset_mit_register()) { @@ -984,11 +989,19 @@ code validate_transaction::check_asset_mit_transaction() const auto&& asset_info = output.get_asset_mit(); asset_symbol = asset_info.get_symbol(); } - else if (output.is_etp()) { - if (!check_same(asset_address, output.get_script_address())) { + else if (output.is_etp() || output.is_asset_transfer()) { + } + else if (output.is_asset_cert()) { + asset_cert&& cert_info = output.get_asset_cert(); + if (cert_info.get_type() == asset_cert_ns::domain) { + if (!check_same(cert_owner, cert_info.get_owner())) { + return error::mit_register_error; + } + } + else { log::debug(LOG_BLOCKCHAIN) << "MIT: " - << " address is not same. " - << asset_address << " != " << output.get_script_address(); + << " the cert is not domain. " + << cert_info.get_type() << " != " << asset_cert_ns::domain; return error::mit_register_error; } } @@ -1017,13 +1030,7 @@ code validate_transaction::check_asset_mit_transaction() const } auto prev_output = prev_tx.outputs.at(input.previous_output.index); - if (prev_output.is_etp()) { - auto&& asset_address_in = prev_output.get_script_address(); - if (asset_address != asset_address_in) { - log::debug(LOG_BLOCKCHAIN) << "MIT: invalid input address to pay fee: " - << asset_address_in << " != " << asset_address; - return error::validate_inputs_failed; - } + if (prev_output.is_etp() || prev_output.is_asset()) { } else if (prev_output.is_asset_mit()) { auto&& asset_info = prev_output.get_asset_mit(); @@ -1792,7 +1799,7 @@ bool validate_transaction::connect_input( const transaction& previous_tx, uint64 asset_transfer_amount = previous_output.get_asset_amount(); // 2. do asset symbol check - if (!check_same(old_symbol_in_, new_symbol_in)) { + if (!check_same(old_asset_symbol_in_, new_symbol_in)) { return false; } // check forbidden symbol @@ -1807,13 +1814,13 @@ bool validate_transaction::connect_input( const transaction& previous_tx, uint64 } } else if (previous_output.is_asset_mit()) { - if (!check_same(old_symbol_in_, previous_output.get_asset_mit_symbol())) { + if (!check_same(old_mit_symbol_in_, previous_output.get_asset_mit_symbol())) { return false; } } else if (previous_output.is_did()) { // 1. do did symbol check - if (!check_same(old_symbol_in_, previous_output.get_did_symbol())) { + if (!check_same(old_did_symbol_in_, previous_output.get_did_symbol())) { return false; } } @@ -1948,13 +1955,16 @@ bool validate_transaction::check_asset_symbol(const transaction& tx) const { for (const auto& output : tx.outputs) { if (output.is_asset()) { - if (old_symbol_in_ != output.get_asset_symbol()) { + if (old_asset_symbol_in_ != output.get_asset_symbol()) { return false; } } else if (output.is_asset_cert()) { // asset cert related continue; } + else if (output.is_asset_mit_transfer()) { + continue; + } else if (!output.is_etp() && !output.is_message()) { // asset tx only related to asset_cert and etp output return false; @@ -2026,7 +2036,7 @@ bool validate_transaction::check_asset_certs(const transaction& tx) const has_asset_issue = true; } } - else if (!output.is_etp() && !output.is_message()) { + else if (!output.is_etp() && !output.is_message() && !output.is_asset_mit_register()) { // asset cert transfer tx only related to asset_cert and etp output log::debug(LOG_BLOCKCHAIN) << "cert tx mix other illegal output"; return false; @@ -2073,11 +2083,11 @@ bool validate_transaction::check_asset_mit(const transaction& tx) const } auto&& asset_info = output.get_asset_mit(); - if (old_symbol_in_ != asset_info.get_symbol()) { + if (old_mit_symbol_in_ != asset_info.get_symbol()) { return false; } } - else if (!output.is_etp() && !output.is_message()) { + else if (!output.is_etp() && !output.is_asset_transfer() && !output.is_message()) { return false; } } @@ -2089,7 +2099,7 @@ bool validate_transaction::check_did_symbol_match(const transaction& tx) const { for (const auto& output : tx.outputs) { if (output.is_did()) { - if (old_symbol_in_ != output.get_did_symbol()) { + if (old_did_symbol_in_ != output.get_did_symbol()) { return false; } } diff --git a/src/lib/explorer/extensions/base_helper.cpp b/src/lib/explorer/extensions/base_helper.cpp index 6db0d3c7b..587f58f26 100644 --- a/src/lib/explorer/extensions/base_helper.cpp +++ b/src/lib/explorer/extensions/base_helper.cpp @@ -1131,9 +1131,15 @@ void base_transfer_common::sync_fetchutxo( // check cert symbol if (cert_type == asset_cert_ns::domain) { - auto&& domain = asset_cert::get_domain(symbol_); - if (domain != asset_symbol) - continue; + if (symbol_.size() > 0) { + auto&& domain = asset_cert::get_domain(symbol_); + if (domain != asset_symbol) + continue; + } else { + if (payment_domain_set_.find(asset_symbol) == payment_domain_set_.end()) { + continue; + } + } } else if (cert_type == asset_cert_ns::witness) { auto&& primary = asset_cert::get_primary_witness_symbol(symbol_); diff --git a/src/lib/explorer/extensions/commands/registermit.cpp b/src/lib/explorer/extensions/commands/registermit.cpp index 90f5a9d0f..2844bc2a3 100644 --- a/src/lib/explorer/extensions/commands/registermit.cpp +++ b/src/lib/explorer/extensions/commands/registermit.cpp @@ -133,9 +133,39 @@ console_result registermit::invoke (Json::Value& jv_output, throw address_dismatch_account_exception{"target did does not match account. " + to_did}; } + std::string cert_symbol; + chain::asset_cert_type cert_type = asset_cert_ns::none; + std::set payment_domain_set; + // receiver std::vector receiver; for (auto& pair : mit_map) { + // domain cert check + auto&& domain = chain::asset_cert::get_domain(pair.first); + if (chain::asset_cert::is_valid_domain(domain)) { + bool exist = blockchain.is_asset_cert_exist(domain, asset_cert_ns::domain); + if (exist) { + // if domain cert exists then check whether it belongs to the account. + auto cert = blockchain.get_account_asset_cert(auth_.name, domain, asset_cert_ns::domain); + if (cert) { + cert_symbol = domain; + cert_type = cert->get_type(); + + payment_domain_set.insert(domain); + receiver.push_back( + { + to_address, cert_symbol, 0, 0, cert_type, + utxo_attach_type::asset_cert, + chain::attachment("", to_did) + }); + } + else { + throw asset_cert_notfound_exception{ + "Domain cert " + pair.first + " exists on the blockchain and is not owned by " + auth_.name}; + } + } + } + receiver.push_back( { to_address, pair.first, 0, 0, 0, @@ -147,7 +177,7 @@ console_result registermit::invoke (Json::Value& jv_output, auto helper = registering_mit( *this, blockchain, std::move(auth_.name), std::move(auth_.auth), - std::move(to_address), "", std::move(mit_map), + std::move(to_address), "", std::move(mit_map), std::move(payment_domain_set), std::move(receiver), argument_.fee); helper.exec();