1
0
Fork 0
forked from lthn/blockchain

Merge branch 'release2' into develop

This commit is contained in:
cryptozoidberg 2024-03-26 21:16:28 +01:00
commit 46a7c9662e
No known key found for this signature in database
GPG key ID: 2E10CC61CAC8F36D
12 changed files with 167 additions and 62 deletions

View file

@ -85,6 +85,18 @@ namespace epee
}
return res;
}
// helper for blob-to-base64 serialization
inline std::string transfrom_binbuf_to_base64(const std::string& a)
{
return epee::string_encoding::base64_encode(a);
}
inline std::string transform_base64_to_binbuf(const std::string& a)
{
return epee::string_encoding::base64_decode(a);
}
//-------------------------------------------------------------------------------------------------------------------
#pragma pack(push, 1)
template<class first_t, class second_t>

View file

@ -81,6 +81,8 @@ public: \
#define KV_SERIALIZE_BLOB_AS_HEX_STRING_N(varialble, val_name) \
KV_SERIALIZE_CUSTOM_N(varialble, std::string, epee::transform_binbuf_to_hexstr, epee::transform_hexstr_to_binbuff, val_name)
#define KV_SERIALIZE_BLOB_AS_BASE64_STRING_N(varialble, val_name) \
KV_SERIALIZE_CUSTOM_N(varialble, std::string, epee::transfrom_binbuf_to_base64, epee::transform_base64_to_binbuf, val_name)
#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name) \
epee::serialization::selector<is_store>::serialize_t_val_as_blob(this_ref.varialble, stg, hparent_section, val_name);
@ -100,7 +102,8 @@ public: \
#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB(varialble) KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, #varialble)
#define KV_SERIALIZE_CUSTOM(varialble, stored_type, from_v_to_stored, from_stored_to_v) KV_SERIALIZE_CUSTOM_N(varialble, stored_type, from_v_to_stored, from_stored_to_v, #varialble)
#define KV_SERIALIZE_POD_AS_HEX_STRING(varialble) KV_SERIALIZE_POD_AS_HEX_STRING_N(varialble, #varialble)
#define KV_SERIALIZE_BLOB_AS_HEX_STRING(varialble) KV_SERIALIZE_BLOB_AS_HEX_STRING_N(varialble, #varialble)
#define KV_SERIALIZE_BLOB_AS_HEX_STRING(varialble) KV_SERIALIZE_BLOB_AS_HEX_STRING_N(varialble, #varialble)
#define KV_SERIALIZE_BLOB_AS_BASE64_STRING(variable) KV_SERIALIZE_BLOB_AS_BASE64_STRING_N(variable, #variable)

View file

@ -3784,6 +3784,17 @@ uint64_t blockchain_storage::get_aliases_count() const
return m_db_aliases.size();
}
//------------------------------------------------------------------
bool blockchain_storage::get_asset_history(const crypto::public_key& asset_id, std::list<asset_descriptor_operation>& result) const
{
CRITICAL_REGION_LOCAL(m_read_lock);
auto as_ptr = m_db_assets.find(asset_id);
if (!as_ptr)
return false;
result = *as_ptr;
return true;
}
//------------------------------------------------------------------
bool blockchain_storage::get_asset_info(const crypto::public_key& asset_id, asset_descriptor_base& result) const
{
CRITICAL_REGION_LOCAL(m_read_lock);
@ -5447,7 +5458,6 @@ std::shared_ptr<const transaction_chain_entry> blockchain_storage::find_key_imag
//---------------------------------------------------------------
bool blockchain_storage::fill_tx_rpc_details(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce, const crypto::hash& h, uint64_t timestamp, bool is_short) const
{
//tei.blob = tx_ptr->tx
tei.id = epee::string_tools::pod_to_hex(h);
if (!tei.blob_size)
tei.blob_size = get_object_blobsize(tx);
@ -5464,6 +5474,9 @@ bool blockchain_storage::fill_tx_rpc_details(tx_rpc_extended_info& tei, const tr
fill_tx_rpc_outputs(tei, tx, ptce);
fill_tx_rpc_payload_items(tei.extra, tx.extra);
fill_tx_rpc_payload_items(tei.attachments, tx.attachment);
tei.blob = t_serializable_object_to_blob(tx);
tei.object_in_json = obj_to_json_str(tx);
return true;
}
//------------------------------------------------------------------

View file

@ -299,6 +299,7 @@ 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_history(const crypto::public_key& asset_id, std::list<asset_descriptor_operation>& result) const;
bool get_asset_info(const crypto::public_key& 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;

View file

@ -976,8 +976,8 @@ namespace currency
return "(no transactions, the pool is empty)";
// sort output by receive time
txs.sort([](const std::pair<crypto::hash, tx_details>& lhs, const std::pair<crypto::hash, tx_details>& rhs) -> bool { return lhs.second.receive_time < rhs.second.receive_time; });
ss << "# | transaction id | size | fee | ins | outs | outs money | live_time | max used block | last failed block | kept by a block?" << ENDL;
// 1234 f99fe6d4335fc0ddd69e6880a4d95e0f6ea398de0324a6837021a61c6a31cacd 87157 0.10000111 2000 2000 112000.12345678 d0.h10.m16.s17 123456 <12345..> 123456 <12345..> YES
ss << "# | transaction id | size | fee | ins | outs | live_time | max used block | last failed block | ver | kept by a block?" << ENDL;
// 1234 f99fe6d4335fc0ddd69e6880a4d95e0f6ea398de0324a6837021a61c6a31cacd 187157 0.10000111 2000 2000 d0.h10.m16.s17 1234567 <12345..> 1234567 <12345..> 2 YES
size_t i = 0;
for (auto& tx : txs)
{
@ -985,16 +985,16 @@ namespace currency
ss << std::left
<< std::setw(4) << i++ << " "
<< tx.first << " "
<< std::setw(5) << txd.blob_size << " "
<< std::setw(6) << txd.blob_size << " "
<< std::setw(10) << print_money_brief(txd.fee) << " "
<< std::setw(4) << txd.tx.vin.size() << " "
<< std::setw(4) << txd.tx.vout.size() << " "
<< std::right << std::setw(15) << print_money(get_outs_money_amount(txd.tx)) << std::left << " "
<< std::setw(14) << epee::misc_utils::get_time_interval_string(get_core_time() - txd.receive_time) << " "
<< std::setw(6) << txd.max_used_block_height << " "
<< std::setw(7) << txd.max_used_block_height << " "
<< std::setw(9) << print16(txd.max_used_block_id) << " "
<< std::setw(6) << txd.last_failed_height << " "
<< std::setw(7) << txd.last_failed_height << " "
<< std::setw(9) << print16(txd.last_failed_id) << " "
<< std::setw(3) << txd.tx.version << " "
<< (txd.kept_by_block ? "YES" : "no ")
<< ENDL;
}

View file

@ -47,6 +47,7 @@ public:
m_cmd_binder.set_handler("print_block_info", boost::bind(&daemon_commands_handler::print_block_info, this, ph::_1), "Print block info, print_block <block_hash> | <block_height>");
m_cmd_binder.set_handler("print_tx_prun_info", boost::bind(&daemon_commands_handler::print_tx_prun_info, this, ph::_1), "Print tx prunning info");
m_cmd_binder.set_handler("print_tx", boost::bind(&daemon_commands_handler::print_tx, this, ph::_1), "Print transaction, print_tx <transaction_hash>");
m_cmd_binder.set_handler("print_asset_info", boost::bind(&daemon_commands_handler::print_asset_info, this, ph::_1), "Print information about the given asset by its id");
m_cmd_binder.set_handler("start_mining", boost::bind(&daemon_commands_handler::start_mining, this, ph::_1), "Start mining for specified address, start_mining <addr> [threads=1]");
m_cmd_binder.set_handler("stop_mining", boost::bind(&daemon_commands_handler::stop_mining, this, ph::_1), "Stop mining");
m_cmd_binder.set_handler("print_pool", boost::bind(&daemon_commands_handler::print_pool, this, ph::_1), "Print transaction pool (long format)");
@ -688,7 +689,7 @@ private:
{
if (args.empty())
{
std::cout << "expected: print_tx <transaction hash>" << std::endl;
std::cout << "usage: print_tx <transaction hash>" << std::endl;
return true;
}
@ -696,55 +697,74 @@ private:
crypto::hash tx_hash;
if (!parse_hash256(str_hash, tx_hash))
{
LOG_PRINT_RED_L0("invalid tx hash was given");
return true;
}
// std::vector<crypto::hash> tx_ids;
// tx_ids.push_back(tx_hash);
// std::list<currency::transaction> txs;
// std::list<crypto::hash> missed_ids;
// m_srv.get_payload_object().get_core().get_transactions(tx_ids, txs, missed_ids);
currency::transaction_chain_entry tx_entry = AUTO_VAL_INIT(tx_entry);
if (!m_srv.get_payload_object().get_core().get_blockchain_storage().get_tx_chain_entry(tx_hash, tx_entry))
currency::tx_rpc_extended_info tx_rpc_ei{};
currency::core& core = m_srv.get_payload_object().get_core();
if (core.get_blockchain_storage().get_tx_rpc_details(tx_hash, tx_rpc_ei, 0, false))
{
LOG_PRINT_RED("transaction wasn't found: " << tx_hash, LOG_LEVEL_0);
// pass
}
currency::block_extended_info bei = AUTO_VAL_INIT(bei);
m_srv.get_payload_object().get_core().get_blockchain_storage().get_block_extended_info_by_height(tx_entry.m_keeper_block_height, bei);
uint64_t timestamp = bei.bl.timestamp;
const currency::transaction& tx = tx_entry.tx;
std::stringstream ss;
ss << "------------------------------------------------------"
<< ENDL << "tx_id: " << tx_hash
<< ENDL << "keeper_block: " << tx_entry.m_keeper_block_height << ", timestamp (" << timestamp << ") " << epee::misc_utils::get_internet_time_str(timestamp)
<< ENDL << currency::obj_to_json_str(tx)
<< ENDL << "------------------------------------------------------"
<< ENDL << epee::string_tools::buff_to_hex_nodelimer(t_serializable_object_to_blob(tx))
<< ENDL << "------------------------------------------------------";
ss << "ATTACHMENTS: " << ENDL;
for (auto at : tx.attachment)
else if (core.get_tx_pool().get_transaction_details(tx_hash, tx_rpc_ei))
{
if (at.type() == typeid(currency::tx_service_attachment))
{
const currency::tx_service_attachment& sa = boost::get<currency::tx_service_attachment>(at);
ss << "++++++++++++++++++++++++++++++++ " << ENDL;
ss << "[SERVICE_ATTACHMENT]: ID = \'" << sa.service_id << "\', INSTRUCTION: \'" << sa.instruction << "\'" << ENDL;
// pass
}
else
{
LOG_PRINT_RED("transaction " << tx_hash << " was not found in either the blockchain or the pool", LOG_LEVEL_0);
return true;
}
if (!(sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY))
std::stringstream ss;
ss << ENDL <<
"----------------------TX-HEX--------------------------" << ENDL <<
epee::string_tools::buff_to_hex_nodelimer(tx_rpc_ei.blob) << ENDL <<
"------------------END-OF-TX-HEX-----------------------" << ENDL;
ss << ENDL <<
"tx " << tx_hash << " ";
if (tx_rpc_ei.keeper_block == -1)
{
ss << "has been in the transaction pool for " << epee::misc_utils::get_time_interval_string(core.get_blockchain_storage().get_core_runtime_config().get_core_time() - tx_rpc_ei.timestamp) <<
", added " << epee::misc_utils::get_internet_time_str(tx_rpc_ei.timestamp) << ", ts: " << tx_rpc_ei.timestamp << ", blob size: " << tx_rpc_ei.blob_size << ENDL;
}
else
{
ss << "was added to block @ " << tx_rpc_ei.keeper_block << ", block time: " << epee::misc_utils::get_internet_time_str(tx_rpc_ei.timestamp) << ", ts: " << tx_rpc_ei.timestamp << ", blob size: " << tx_rpc_ei.blob_size << ENDL;
}
ss << ENDL <<
"-----------------------JSON---------------------------" << ENDL <<
tx_rpc_ei.object_in_json << ENDL <<
"--------------------END-OF-JSON-----------------------" << ENDL;
currency::transaction tx{};
CHECK_AND_ASSERT_MES(currency::parse_and_validate_tx_from_blob(tx_rpc_ei.blob, tx), true, "parse_and_validate_tx_from_blob failed");
if (!tx.attachment.empty())
{
ss << "ATTACHMENTS: " << ENDL;
for (auto at : tx.attachment)
{
if (at.type() == typeid(currency::tx_service_attachment))
{
std::string body = sa.body;
if (sa.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY)
const currency::tx_service_attachment& sa = boost::get<currency::tx_service_attachment>(at);
ss << "++++++++++++++++++++++++++++++++ " << ENDL;
ss << "[SERVICE_ATTACHMENT]: ID = \'" << sa.service_id << "\', INSTRUCTION: \'" << sa.instruction << "\'" << ENDL;
if (!(sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY))
{
bool r = epee::zlib_helper::unpack(sa.body, body);
CHECK_AND_ASSERT_MES(r, false, "Failed to unpack");
std::string body = sa.body;
if (sa.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY)
{
bool r = epee::zlib_helper::unpack(sa.body, body);
CHECK_AND_ASSERT_MES(r, false, "Failed to unpack");
}
ss << "BODY: " << body << ENDL;
}
ss << "BODY: " << body << ENDL;
}
}
}
@ -753,6 +773,56 @@ private:
return true;
}
//--------------------------------------------------------------------------------
bool print_asset_info(const std::vector<std::string>& args)
{
if (args.empty())
{
std::cout << "usage: print_asset_info <asset_id>" << std::endl;
return true;
}
const std::string& str_asset_id = args.front();
crypto::public_key asset_id{};
crypto::point_t asset_id_pt{};
if (!crypto::parse_tpod_from_hex_string(str_asset_id, asset_id) || !asset_id_pt.from_public_key(asset_id))
{
LOG_PRINT_RED_L0("invalid asset id was given");
return true;
}
currency::core& core = m_srv.get_payload_object().get_core();
std::list<currency::asset_descriptor_operation> asset_history;
if (!core.get_blockchain_storage().get_asset_history(asset_id, asset_history))
{
LOG_PRINT_RED_L0("asset id doesn't present in the blockchain");
return true;
}
std::stringstream ss;
ss << ENDL <<
"history for asset " << asset_id << ":" << ENDL;
size_t idx = 0;
for(auto& aop: asset_history)
{
ss << "[" << std::setw(2) << idx << "] operation: " << currency::get_asset_operation_type_string(aop.operation_type) << " (" << (int)aop.operation_type << ")" << ENDL <<
" ticker: \"" << aop.descriptor.ticker << "\"" << ENDL <<
" full name: \"" << aop.descriptor.full_name << "\"" << ENDL <<
" meta info: \"" << aop.descriptor.meta_info << "\"" << ENDL <<
" current supply: " << currency::print_money_brief(aop.descriptor.current_supply, aop.descriptor.decimal_point) << ENDL <<
" max supply: " << currency::print_money_brief(aop.descriptor.total_max_supply, aop.descriptor.decimal_point) << ENDL <<
" decimal point: " << (int)aop.descriptor.decimal_point << ENDL <<
" owner * 1/8: " << aop.descriptor.owner << ENDL <<
" amount cmt * 1/8: " << aop.amount_commitment << ENDL <<
" hidden supply: " << (aop.descriptor.hidden_supply ? "yes" : "no") << ENDL <<
"";
}
LOG_PRINT_L0(ss.str());
return true;
}
//--------------------------------------------------------------------------------
bool print_tx_outputs_usage(const std::vector<std::string>& args)
{
if (args.empty())

View file

@ -1344,7 +1344,7 @@ namespace currency
std::string object_in_json;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(blob)
KV_SERIALIZE_BLOB_AS_BASE64_STRING(blob)
KV_SERIALIZE(blob_size)
KV_SERIALIZE(timestamp)
KV_SERIALIZE(keeper_block)
@ -1356,7 +1356,7 @@ namespace currency
KV_SERIALIZE(ins)
KV_SERIALIZE(extra)
KV_SERIALIZE(attachments)
KV_SERIALIZE(object_in_json)
KV_SERIALIZE_BLOB_AS_BASE64_STRING(object_in_json)
END_KV_SERIALIZE_MAP()
};

View file

@ -2119,11 +2119,11 @@ bool simple_wallet::emit_asset(const std::vector<std::string> &args)
tx_destination_entry td = AUTO_VAL_INIT(td);
td.addr.push_back(m_wallet->get_account().get_public_address());
td.amount = amount;
td.asset_id = asset_id;
td.asset_id = currency::null_pkey;
std::vector<currency::tx_destination_entry> destinations;
destinations.push_back(td);
currency::transaction result_tx = AUTO_VAL_INIT(result_tx);
m_wallet->emmit_asset(asset_id, destinations, result_tx);
m_wallet->emit_asset(asset_id, destinations, result_tx);
success_msg_writer(true) << "Emitted " << get_transaction_hash(result_tx) << " (unconfirmed) : " << ENDL
<< "Asset ID: " << asset_id << ENDL

View file

@ -8,6 +8,6 @@
#define PROJECT_REVISION "0"
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
#define PROJECT_VERSION_BUILD_NO 286
#define PROJECT_VERSION_BUILD_NO 287
#define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO)
#define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]"

View file

@ -5008,7 +5008,7 @@ void wallet2::deploy_new_asset(const currency::asset_descriptor_base& asset_info
m_custom_assets[new_asset_id] = ado.descriptor;
}
//----------------------------------------------------------------------------------------------------
void wallet2::emmit_asset(const crypto::public_key asset_id, std::vector<currency::tx_destination_entry>& destinations, currency::transaction& result_tx)
void wallet2::emit_asset(const crypto::public_key asset_id, std::vector<currency::tx_destination_entry>& destinations, currency::transaction& result_tx)
{
auto own_asset_entry_it = m_own_asset_descriptors.find(asset_id);
@ -5030,6 +5030,12 @@ void wallet2::emmit_asset(const crypto::public_key asset_id, std::vector<currenc
ctp.ado_current_asset_owner = rsp.asset_descriptor.owner;
//ctp.asset_deploy_control_key = own_asset_entry_it->second.control_key;
for(auto& dst : ctp.dsts)
{
if (dst.asset_id == asset_id)
dst.asset_id = null_pkey; // emit operation requires null_pkey for emitting asset outputs, fix it ad-hoc here
}
finalized_tx ft = AUTO_VAL_INIT(ft);
this->transfer(ctp, ft, true, nullptr);
result_tx = ft.tx;

View file

@ -394,7 +394,7 @@ namespace tools
bool check_available_sources(std::list<uint64_t>& amounts);
void deploy_new_asset(const currency::asset_descriptor_base& asset_info, const std::vector<currency::tx_destination_entry>& destinations, currency::transaction& result_tx, crypto::public_key& new_asset_id);
void emmit_asset(const crypto::public_key asset_id, std::vector<currency::tx_destination_entry>& destinations, currency::transaction& result_tx);
void emit_asset(const crypto::public_key asset_id, std::vector<currency::tx_destination_entry>& destinations, currency::transaction& result_tx);
void update_asset(const crypto::public_key asset_id, const currency::asset_descriptor_base new_descriptor, currency::transaction& result_tx);
void burn_asset(const crypto::public_key asset_id, uint64_t amount_to_burn, currency::transaction& result_tx);
void transfer_asset_ownership(const crypto::public_key asset_id, const crypto::public_key& new_owner, currency::transaction& result_tx);

View file

@ -142,9 +142,9 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
CHECK_AND_ASSERT_MES(asset_info2.meta_info == asset_info.meta_info, false, "Failed to find needed asset in result balances");
//test emmit function
//test emit function
//use same destinations as we used before
miner_wlt->emmit_asset(asset_id, destinations, tx);
miner_wlt->emit_asset(asset_id, destinations, tx);
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");
@ -252,13 +252,13 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
//miner_wlt->refresh();
// check emmit_asset() with modified 'current_supply'
// check emit_asset() with modified 'current_supply'
miner_wlt->get_debug_events_dispatcher().SUBSCIRBE_DEBUG_EVENT<wde_construct_tx_handle_asset_descriptor_operation_before_seal>([&](const wde_construct_tx_handle_asset_descriptor_operation_before_seal& o)
{
o.pado->descriptor.current_supply += 1000000;
});
//test emmit function but re-adjust current_supply to wrong amount
miner_wlt->emmit_asset(asset_id, destinations, tx);
//test emit function but re-adjust current_supply to wrong amount
miner_wlt->emit_asset(asset_id, destinations, tx);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c);
CHECK_AND_ASSERT_MES(!r, false, "block with a bad tx was unexpectedly mined");
@ -305,7 +305,7 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
uint64_t balance_alice_asset = alice_wlt->balance(asset_id);
uint64_t balance_miner_asset = miner_wlt->balance(asset_id);
alice_wlt->emmit_asset(asset_id, destinations, tx);
alice_wlt->emit_asset(asset_id, destinations, tx);
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");
@ -315,7 +315,7 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
CHECK_AND_ASSERT_MES(miner_wlt->balance(asset_id) == balance_miner_asset + destinations[0].amount, false, "Miner balance wrong");
CHECK_AND_ASSERT_MES(alice_wlt->balance(asset_id) == balance_alice_asset + destinations[1].amount, false, "Alice balance wrong");
//TODO: attempt to emmmit from old key, attempt to emmit from more then max supply
//TODO: attempt to emmmit from old key, attempt to emit from more then max supply
return true;
}