From 0c1fe0cf804b6b943757b015dcda4044af05cc4f Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 21 May 2024 02:17:58 +0200 Subject: [PATCH 01/53] Dockerfile brought up-to-date --- utils/docker/Dockerfile | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/utils/docker/Dockerfile b/utils/docker/Dockerfile index 580c2a31..4394a6db 100644 --- a/utils/docker/Dockerfile +++ b/utils/docker/Dockerfile @@ -31,26 +31,32 @@ FROM ubuntu:18.04 as build-prep +ENV DEBIAN_FRONTEND noninteractive + RUN apt update && \ apt install -y build-essential \ libicu-dev \ + libz-dev \ curl \ - g++ \ + gcc-8 \ + g++-8 \ git +RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 700 --slave /usr/bin/g++ g++ /usr/bin/g++-7 && \ + update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 800 --slave /usr/bin/g++ g++ /usr/bin/g++-8 WORKDIR /root # Lib Settings -ARG CMAKE_VERSION_DOT=3.15.5 -ARG CMAKE_HASH=62e3e7d134a257e13521e306a9d3d1181ab99af8fcae66699c8f98754fc02dda +ARG CMAKE_VERSION_DOT=3.16.9 +ARG CMAKE_HASH=d71eda07d6ecf3964de65a0e36d0b171565e1aced56ba9f53ca3783406b5cacf ARG BOOST_VERSION=1_70_0 ARG BOOST_VERSION_DOT=1.70.0 ARG BOOST_HASH=430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778 -ARG OPENSSL_VERSION_DOT=1.1.1n -ARG OPENSSL_HASH=40dceb51a4f6a5275bde0e6bf20ef4b91bfc32ed57c0552e2e8e15463372b17a +ARG OPENSSL_VERSION_DOT=1.1.1w +ARG OPENSSL_HASH=cf3098950cb4d853ad95c0841f1f9c6d3dc102dccfcacd521d93925208b76ac8 # Environment Variables ENV BOOST_ROOT /root/boost_${BOOST_VERSION} @@ -68,7 +74,7 @@ RUN set -ex \ # Download Boost RUN set -ex \ && curl -L -o boost_${BOOST_VERSION}.tar.bz2 https://downloads.sourceforge.net/project/boost/boost/${BOOST_VERSION_DOT}/boost_${BOOST_VERSION}.tar.bz2 \ - && sha256sum boost_${BOOST_VERSION}.tar.bz2 \ + && sha256sum boost_${BOOST_VERSION}.tar.bz2 \ && echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c\ && tar -xvf boost_${BOOST_VERSION}.tar.bz2 @@ -82,10 +88,10 @@ RUN curl https://www.openssl.org/source/openssl-${OPENSSL_VERSION_DOT}.tar.gz -O # Compile CMake RUN set -ex \ && mkdir /opt/cmake \ - && sh cmake-3.15.5-Linux-x86_64.sh --prefix=/opt/cmake --skip-license\ + && sh cmake-3.16.9-Linux-x86_64.sh --prefix=/opt/cmake --skip-license\ && ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake\ && cmake --version\ - && rm cmake-3.15.5-Linux-x86_64.sh + && rm cmake-3.16.9-Linux-x86_64.sh # Compile Boost RUN set -ex \ From d0bad4213ae8c8deabd0c18e3acc8d6abcd5367c Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Sat, 25 May 2024 01:11:01 +0400 Subject: [PATCH 02/53] fixed bug in rpc asset deploy function --- src/wallet/wallet_rpc_server.cpp | 2 +- tests/performance_tests/main.cpp | 42 +++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 10d2a399..e9f769f9 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -1246,7 +1246,7 @@ namespace tools std::string embedded_payment_id; //check if address looks like wrapped address WLT_THROW_IF_FALSE_WITH_CODE(!currency::is_address_like_wrapped(it->address), "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS", "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS"); - WLT_THROW_IF_FALSE_WITH_CODE(!w.get_wallet()->get_transfer_address(it->address, de.addr.back(), embedded_payment_id), "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS", "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS"); + WLT_THROW_IF_FALSE_WITH_CODE(w.get_wallet()->get_transfer_address(it->address, de.addr.back(), embedded_payment_id), "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS", "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS"); WLT_THROW_IF_FALSE_WITH_CODE(embedded_payment_id.size() == 0, "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS", "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS"); de.amount = it->amount; de.asset_id = it->asset_id; diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index 58fbd85f..1055bfca 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -34,8 +34,8 @@ POP_VS_WARNINGS void test_plain_wallet() { - //std::string res = plain_wallet::init("195.201.107.230", "33336", "E:\\tmp\\", 0); - std::string res = plain_wallet::init("127.0.0.1", "12111", "C:\\Users\\roky\\home22\\", 0); + std::string res = plain_wallet::init("195.201.107.230", "33340", "C:\\Users\\roky\\home\\", 0); + //std::string res = plain_wallet::init("127.0.0.1", "12111", "C:\\Users\\roky\\home22\\", 0); std::string res___ = plain_wallet::get_wallet_files(); @@ -60,21 +60,45 @@ void test_plain_wallet() std::string invoke_body = "{\"method\":\"store\",\"params\":{}}"; std::string res1 = plain_wallet::sync_call("invoke", instance_id, invoke_body); - invoke_body = "{\"method\":\"get_recent_txs_and_info\",\"params\":{\"offset\":0,\"count\":30,\"update_provision_info\":true}}"; - std::string res2 = plain_wallet::sync_call("invoke", instance_id, invoke_body); + { + invoke_body = "{\"method\":\"getbalance\",\"params\":{}}"; + std::string res3 = plain_wallet::sync_call("invoke", instance_id, invoke_body); + invoke_body = ""; + } - invoke_body = "{\"method\":\"get_recent_txs_and_info2\",\"params\":{\"offset\":0,\"count\":30,\"update_provision_info\":true}}"; - res2 = plain_wallet::sync_call("invoke", instance_id, invoke_body); + { + invoke_body = "{\"method\":\"assets_whitelist_get\",\"params\":{}}"; + std::string res3 = plain_wallet::sync_call("invoke", instance_id, invoke_body); + invoke_body = ""; + } + + + + { + //invoke_body = "{\"method\":\"assets_whitelist_get\",\"params\":{}}"; + //std::string json_request; + bool r = epee::file_io_utils::load_file_to_string("C:\\Users\\roky\\home\\wallets\\deploy_asset_request.json", invoke_body); + CHECK_AND_ASSERT_MES(r, void(), "wrong bla bla bla"); + std::string res3 = plain_wallet::sync_call("invoke", instance_id, invoke_body); + invoke_body = ""; + } + + + //invoke_body = "{\"method\":\"get_recent_txs_and_info\",\"params\":{\"offset\":0,\"count\":30,\"update_provision_info\":true}}"; + //std::string res2 = plain_wallet::sync_call("invoke", instance_id, invoke_body); + + //invoke_body = "{\"method\":\"get_recent_txs_and_info2\",\"params\":{\"offset\":0,\"count\":30,\"update_provision_info\":true}}"; + //res2 = plain_wallet::sync_call("invoke", instance_id, invoke_body); invoke_body = "{\"method\":\"getbalance\",\"params\":{}}"; std::string res3 = plain_wallet::sync_call("invoke", instance_id, invoke_body); - invoke_body = "{\r\n \"method\": \"transfer\",\r\n \"params\": {\r\n \"destinations\": [\r\n {\r\n \"amount\": \"1000000000000\",\r\n \"address\": \"ZxD9oVwGwW6ULix9Pqttnr7JDpaoLvDVA1KJ9eA9KRxPMRZT5X7WwtU94XH1Z6q6XTMxNbHmbV2xfZ429XxV6fST2DxEg4BQV\",\r\n \"asset_id\": \"cc4e69455e63f4a581257382191de6856c2156630b3fba0db4bdd73ffcfb36b6\"\r\n }\r\n ],\r\n \"fee\": 10000000000,\r\n \"mixin\": 10,\r\n \"payment_id\": \"\",\r\n \"comment\": \"\",\r\n \"push_payer\": false,\r\n \"hide_receiver\": true\r\n }\r\n}"; - std::string res4 = plain_wallet::sync_call("invoke", instance_id, invoke_body); + //invoke_body = "{\r\n \"method\": \"transfer\",\r\n \"params\": {\r\n \"destinations\": [\r\n {\r\n \"amount\": \"1000000000000\",\r\n \"address\": \"ZxD9oVwGwW6ULix9Pqttnr7JDpaoLvDVA1KJ9eA9KRxPMRZT5X7WwtU94XH1Z6q6XTMxNbHmbV2xfZ429XxV6fST2DxEg4BQV\",\r\n \"asset_id\": \"cc4e69455e63f4a581257382191de6856c2156630b3fba0db4bdd73ffcfb36b6\"\r\n }\r\n ],\r\n \"fee\": 10000000000,\r\n \"mixin\": 10,\r\n \"payment_id\": \"\",\r\n \"comment\": \"\",\r\n \"push_payer\": false,\r\n \"hide_receiver\": true\r\n }\r\n}"; + //std::string res4 = plain_wallet::sync_call("invoke", instance_id, invoke_body); - LOG_PRINT_L0(res); + //LOG_PRINT_L0(res); } From 092e0f1e609903827c93b7f823a6cb07a997470b Mon Sep 17 00:00:00 2001 From: sowle Date: Fri, 31 May 2024 15:49:55 +0200 Subject: [PATCH 03/53] minor improvements, typos, log msgs --- src/common/variant_helper.h | 2 +- src/currency_core/blockchain_storage.cpp | 4 ++-- src/currency_core/currency_format_utils.cpp | 12 ++++++++++-- src/wallet/wallet2.cpp | 2 +- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/common/variant_helper.h b/src/common/variant_helper.h index 9f98cbaa..4eb12546 100644 --- a/src/common/variant_helper.h +++ b/src/common/variant_helper.h @@ -9,7 +9,7 @@ #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()); +#define VARIANT_CASE_THROW_ON_OTHER() } else { ASSERT_MES_AND_THROW("Unknown type in switch statement: " << local_reference_eokcmeokmeokcm.type().name()); #define VARIANT_CASE_THROW_ON_OTHER_MSG(err_msg) } else { ASSERT_MES_AND_THROW(err_msg << local_reference_eokcmeokmeokcm.type().name()); #define VARIANT_SWITCH_END() } } diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index a16302f1..3414f213 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -1882,7 +1882,7 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto:: // miner tx prevalidation (light checks) if (!prevalidate_miner_transaction(b, abei.height, pos_block)) { - LOG_PRINT_RED_L0("Alternative block " << id << " @ " << coinbase_height << "has invalid miner transaction."); + LOG_PRINT_RED_L0("Alternative block " << id << " @ " << coinbase_height << " has invalid miner transaction."); bvc.m_verification_failed = true; return false; } @@ -4990,7 +4990,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, scan_for_keys_context scan_context = AUTO_VAL_INIT(scan_context); if(!get_output_keys_for_input_with_checks(tx, txin, output_keys, max_related_block_height, source_max_unlock_time_for_pos_coinbase)) { - LOG_PRINT_L0("Failed to get output keys for input #" << in_index << " (amount = " << print_money(txin.amount) << ", key_offset.size = " << txin.key_offsets.size() << ")"); + LOG_PRINT_L0("Failed to get output keys for input #" << in_index << " (amount = " << print_money_brief(txin.amount) << ", key_offset.size = " << txin.key_offsets.size() << "), tx: " << tx_prefix_hash); return false; } //TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_ch_in_get_keys_loop); diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 5f4fa38f..556f371e 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2023 Zano Project +// Copyright (c) 2014-2024 Zano Project // Copyright (c) 2014-2018 The Louisdor Project // Copyright (c) 2012-2013 The Cryptonote developers // Copyright (c) 2012-2013 The Boolberry developers @@ -355,7 +355,7 @@ namespace currency CHECK_AND_ASSERT_MES(commitment_to_zero_is_sane, false, "internal error: commitment_to_zero is malformed (X)"); #endif r = crypto::generate_double_schnorr_sig(tx_id, commitment_to_zero, secret_x, ogc.tx_pub_key_p, ogc.tx_key.sec, proof.dss); - CHECK_AND_ASSERT_MES(r, false, "genergenerate_double_schnorr_sigate_schnorr_sig (X, G) failed"); + CHECK_AND_ASSERT_MES(r, false, "generate_double_schnorr_sig (X, G) failed"); } return true; @@ -700,6 +700,14 @@ namespace currency // (sum(bare inputs' amounts) - fee) * H + sum(pseudo outs commitments for ZC inputs) - sum(outputs' commitments) = lin(X) OR = lin(G) crypto::point_t commitment_to_zero = (crypto::scalar_t(bare_inputs_sum) - crypto::scalar_t(fee)) * currency::native_coin_asset_id_pt + sum_of_pseudo_out_amount_commitments - outs_commitments_sum; + DBG_VAL_PRINT(tx_id); + DBG_VAL_PRINT(tx_pub_key); + DBG_VAL_PRINT(bare_inputs_sum); + DBG_VAL_PRINT(fee); + DBG_VAL_PRINT(sum_of_pseudo_out_amount_commitments); + DBG_VAL_PRINT(outs_commitments_sum); + DBG_VAL_PRINT(commitment_to_zero); + CHECK_AND_ASSERT_MES(zc_inputs_count == zc_sigs_count, false, "zc inputs count (" << zc_inputs_count << ") and zc sigs count (" << zc_sigs_count << ") missmatch"); if (zc_inputs_count > 0) { diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index d5720fe3..a48d5455 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -4782,7 +4782,7 @@ bool wallet2::prepare_and_sign_pos_block(const mining_context& cxt, uint64_t ful crypto::hash hash_for_zarcanum_sig = get_block_hash(b); - WLT_CHECK_AND_ASSERT_MES(miner_tx_tgc.pseudo_out_amount_blinding_masks_sum.is_zero(), false, "pseudo_out_amount_blinding_masks_sum is nonzero"); // it should be zero because there's only one input (stake), and thus one pseudo out + WLT_CHECK_AND_ASSERT_MES(miner_tx_tgc.pseudo_out_amount_blinding_masks_sum.is_zero(), false, "pseudo_out_amount_blinding_masks_sum is nonzero"); // it should be zero because there's only one ZC input (stake), and thus only one pseudo out (the sum is non-zero iff POC > 1) crypto::scalar_t pseudo_out_amount_blinding_mask = miner_tx_tgc.amount_blinding_masks_sum; // sum of outputs' amount blinding masks miner_tx_tgc.pseudo_outs_blinded_asset_ids.emplace_back(currency::native_coin_asset_id_pt); // for Zarcanum stake inputs pseudo outputs commitments has explicit native asset id From c92ca6fb935baeb5c412279cf23a7682928deaa0 Mon Sep 17 00:00:00 2001 From: sowle Date: Fri, 31 May 2024 15:51:42 +0200 Subject: [PATCH 04/53] chaingen: --run-single-test now accepts specific HF, e.g.: --run-single-test=test_name@4 --- tests/core_tests/chaingen_main.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index aad760ea..6eb28944 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -26,7 +26,7 @@ namespace const command_line::arg_descriptor arg_play_test_data ("play-test-data", ""); const command_line::arg_descriptor arg_generate_and_play_test_data ("generate-and-play-test-data", ""); const command_line::arg_descriptor arg_test_transactions ("test-transactions", ""); - const command_line::arg_descriptor arg_run_single_test ("run-single-test", "" ); + const command_line::arg_descriptor arg_run_single_test ("run-single-test", " TEST_NAME -- name of a single test to run, HF -- specific hardfork id to run the test for" ); const command_line::arg_descriptor arg_enable_debug_asserts ("enable-debug-asserts", "" ); const command_line::arg_descriptor arg_stop_on_fail ("stop-on-fail", ""); @@ -428,6 +428,8 @@ bool gen_and_play_intermitted_by_blockchain_saveload(const char* const genclass_ CHECK_AND_ASSERT_MES(!hardforks.empty(), false, "invalid hardforks mask: " << hardfork_str_mask); \ for(size_t i = 0; i < hardforks.size() && !skip_all_till_the_end; ++i) \ { \ + if (run_single_test_hardfork != SIZE_MAX && hardforks[i] != run_single_test_hardfork) \ + continue; \ std::string tns = std::string(#genclass) + " @ HF " + epee::string_tools::num_to_string_fast(hardforks[i]); \ const char* testname = tns.c_str(); \ TIME_MEASURE_START_MS(t); \ @@ -916,9 +918,19 @@ int main(int argc, char* argv[]) epee::debug::get_set_enable_assert(true, command_line::get_arg(g_vm, arg_enable_debug_asserts)); // don't comment out this: many tests have normal-negative checks (i.e. tx with invalid amount shouldn't be created), so be ready for MANY assertion breaks std::string run_single_test; + size_t run_single_test_hardfork = SIZE_MAX; // SIZE_MAX means all hard forks, other values mean hardfork id if (command_line::has_arg(g_vm, arg_run_single_test)) { - run_single_test = command_line::get_arg(g_vm, arg_run_single_test); + std::vector items; + boost::split(items, command_line::get_arg(g_vm, arg_run_single_test), boost::is_any_of("@")); + CHECK_AND_ASSERT_MES(items.size() > 0, 2, "unable to parse arg_run_single_test"); + run_single_test = items[0]; + if (items.size() > 1) + { + int64_t val = 0; + epee::string_tools::string_to_num_fast(items[1], val); + run_single_test_hardfork = val; + } } if (run_single_test.empty()) From fdc8bf19e04b50cd346cb8930a6244a6fe0a62aa Mon Sep 17 00:00:00 2001 From: sowle Date: Fri, 31 May 2024 16:05:52 +0200 Subject: [PATCH 05/53] gcc compilation fix --- tests/core_tests/chaingen_main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 6eb28944..faac4720 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -921,8 +921,9 @@ int main(int argc, char* argv[]) size_t run_single_test_hardfork = SIZE_MAX; // SIZE_MAX means all hard forks, other values mean hardfork id if (command_line::has_arg(g_vm, arg_run_single_test)) { + std::string arg = command_line::get_arg(g_vm, arg_run_single_test); std::vector items; - boost::split(items, command_line::get_arg(g_vm, arg_run_single_test), boost::is_any_of("@")); + boost::split(items, arg, boost::is_any_of("@")); CHECK_AND_ASSERT_MES(items.size() > 0, 2, "unable to parse arg_run_single_test"); run_single_test = items[0]; if (items.size() > 1) From 66f2761f675478be8ed4fd09fce7507362329ce0 Mon Sep 17 00:00:00 2001 From: sowle Date: Sat, 1 Jun 2024 21:12:26 +0200 Subject: [PATCH 06/53] chaingen: find_global_index_for_output, generate_pos_block_with_given_coinstake adapted for HF4; decode_output_amount_and_asset_id, decode_native_output_amount_or_throw added --- tests/core_tests/chaingen.cpp | 102 +++++++++++++++++++++++++++++----- tests/core_tests/chaingen.h | 17 +++++- 2 files changed, 101 insertions(+), 18 deletions(-) diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 21005216..750b0474 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -2016,14 +2016,13 @@ bool find_global_index_for_output(const std::vector& events, c std::map global_outputs; // amount -> outs count auto process_tx = [&reference_tx, &reference_tx_out_index, &global_outputs](const currency::transaction& tx) -> uint64_t { - for (size_t tx_out_index = 0; tx_out_index < tx.vout.size(); ++tx_out_index) { - const tx_out_bare &out = boost::get(tx.vout[tx_out_index]); - if (out.target.type() == typeid(txout_to_key)) { - uint64_t global_out_index = global_outputs[out.amount]++; + for (size_t tx_out_index = 0; tx_out_index < tx.vout.size(); ++tx_out_index) + { + uint64_t amount = get_amount_from_variant(tx.vout[tx_out_index]); + uint64_t global_out_index = global_outputs[amount]++; - if (tx_out_index == reference_tx_out_index && tx == reference_tx) - return global_out_index; - } + if (tx_out_index == reference_tx_out_index && tx == reference_tx) + return global_out_index; } return UINT64_MAX; }; @@ -2238,32 +2237,105 @@ bool refresh_wallet_and_check_balance(const char* intro_log_message, const char* return true; } -bool generate_pos_block_with_given_coinstake(test_generator& generator, const std::vector &events, const currency::account_base& miner, const currency::block& prev_block, const currency::transaction& stake_tx, size_t stake_output_idx, currency::block& result, uint64_t stake_output_gidx /* = UINT64_MAX */) +bool decode_output_amount_and_asset_id(const crypto::secret_key& view_secret_key, const crypto::public_key& tx_pub_key, const tx_out_v& out_v, size_t output_index, uint64_t &amount, crypto::public_key* p_asset_id = nullptr) { + VARIANT_SWITCH_BEGIN(out_v) + VARIANT_CASE_CONST(currency::tx_out_bare, ob) + if (p_asset_id) + *p_asset_id = native_coin_asset_id; + amount = ob.amount; + return true; + VARIANT_CASE_CONST(currency::tx_out_zarcanum, oz) + crypto::key_derivation derivation{}; + CHECK_AND_ASSERT_MES(crypto::generate_key_derivation(tx_pub_key, view_secret_key, derivation), false, "generate_key_derivation failed"); + crypto::public_key decoded_asset_id{}; + crypto::scalar_t amount_blinding_mask{}; + crypto::scalar_t asset_id_blinding_mask{}; + CHECK_AND_ASSERT_MES(decode_output_amount_and_asset_id(oz, derivation, output_index, amount, decoded_asset_id, amount_blinding_mask, asset_id_blinding_mask), false, "decode_output_amount_and_asset_id failed (wrong keys?)"); + if (p_asset_id) + *p_asset_id = decoded_asset_id; + return true; + VARIANT_CASE_OTHER() + CHECK_AND_ASSERT_MES(false, false, "unexpected output type: " << VARIANT_OBJ_TYPENAME); + VARIANT_SWITCH_END() +} + +bool decode_output_amount_and_asset_id(const account_base& acc, const transaction& tx, size_t output_index, uint64_t &amount, crypto::public_key* p_asset_id /*= nullptr*/) +{ + return decode_output_amount_and_asset_id(acc.get_keys().view_secret_key, get_tx_pub_key_from_extra(tx), tx.vout[output_index], output_index, amount, p_asset_id); +} + +uint64_t decode_native_output_amount_or_throw(const account_base& acc, const transaction& tx, size_t output_index) +{ + crypto::public_key asset_id{}; + uint64_t amount = UINT64_MAX; + bool r = decode_output_amount_and_asset_id(acc.get_keys().view_secret_key, get_tx_pub_key_from_extra(tx), tx.vout[output_index], output_index, amount, &asset_id); + CHECK_AND_ASSERT_THROW_MES(r, "decode_output_amount_and_asset_id failed"); + r = (asset_id == native_coin_asset_id); + CHECK_AND_ASSERT_THROW_MES(r, "wrong asset_id: not native coin"); + return amount; +} + +bool generate_pos_block_with_given_coinstake(test_generator& generator, const std::vector &events, const currency::account_base& miner, const currency::block& prev_block, + const currency::transaction& stake_tx, size_t stake_output_idx, currency::block& result, uint64_t stake_output_gidx /* = UINT64_MAX */) +{ + bool r = false; crypto::hash prev_id = get_block_hash(prev_block); size_t height = get_block_height(prev_block) + 1; - currency::wide_difficulty_type diff = generator.get_difficulty_for_next_block(prev_id, false); + //currency::wide_difficulty_type diff = generator.get_difficulty_for_next_block(prev_id, false); + + currency::wide_difficulty_type pos_diff{}; + crypto::hash last_pow_block_hash{}, last_pos_block_kernel_hash{}; + r = generator.get_params_for_next_pos_block(prev_id, pos_diff, last_pow_block_hash, last_pos_block_kernel_hash); + CHECK_AND_ASSERT_MES(r, false, "get_params_for_next_pos_block failed"); try { crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake_tx); if (stake_output_gidx == UINT64_MAX) { - bool r = find_global_index_for_output(events, prev_id, stake_tx, stake_output_idx, stake_output_gidx); + r = find_global_index_for_output(events, prev_id, stake_tx, stake_output_idx, stake_output_gidx); CHECK_AND_ASSERT_MES(r, false, "find_global_index_for_output failed"); } - uint64_t stake_output_amount =boost::get( stake_tx.vout[stake_output_idx]).amount; + uint64_t stake_output_amount = decode_native_output_amount_or_throw(miner, stake_tx, stake_output_idx); + crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(miner.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(boost::get(stake_tx.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(generator.get_hardforks(), height, prev_id); pb.step2_set_txs(std::vector()); - pb.step3_build_stake_kernel(stake_output_amount, stake_output_gidx, stake_output_key_image, diff, prev_id, null_hash, prev_block.timestamp); - pb.step4_generate_coinbase_tx(generator.get_timestamps_median(prev_id), generator.get_already_generated_coins(prev_block), miner.get_public_address()); - pb.step5_sign(stake_tx_pub_key, stake_output_idx, stake_output_pubkey, miner); + + if (pb.m_context.zarcanum) + { + std::vector sources; + r = fill_tx_sources(sources, events, prev_block, miner.get_keys(), UINT64_MAX /* <- to get all possible entries*/, 0 /* nmix */, false /* check_for_spends*/, false /* check_for_unlocktime*/, false); + //CHECK_AND_ASSERT_MES(r, false, "fill_tx_sources failed"); + bool found = false; + for(const auto& se : sources) + { + if (se.real_output_in_tx_index == stake_output_idx && se.real_out_tx_key == stake_tx_pub_key) + { + found = true; + pb.step3a(pos_diff, last_pow_block_hash, last_pos_block_kernel_hash); + pb.step3b(se.amount, stake_output_key_image, se.real_out_tx_key, se.real_output_in_tx_index, se.real_out_amount_blinding_mask, miner.get_keys().view_secret_key, + stake_output_gidx, prev_block.timestamp, POS_SCAN_WINDOW, POS_SCAN_STEP); + pb.step4_generate_coinbase_tx(generator.get_timestamps_median(prev_id), generator.get_already_generated_coins(prev_block), miner.get_public_address()); + pb.step5_sign(se, miner.get_keys()); + break; + } + } + CHECK_AND_ASSERT_MES(found, false, "required source entry could not be found (difficult case, ask sowle)"); + } + else + { + pb.step3_build_stake_kernel(stake_output_amount, stake_output_gidx, stake_output_key_image, pos_diff, last_pow_block_hash, last_pos_block_kernel_hash, prev_block.timestamp); + pb.step4_generate_coinbase_tx(generator.get_timestamps_median(prev_id), generator.get_already_generated_coins(prev_block), miner.get_public_address()); + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake_tx.vout[stake_output_idx]).target).key; + pb.step5_sign(stake_tx_pub_key, stake_output_idx, stake_output_pubkey, miner); + } + result = pb.m_block; return true; diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index 087e0c3a..d8d49100 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -741,6 +741,10 @@ bool refresh_wallet_and_check_balance(const char* intro_log_message, const char* uint64_t expected_awaiting_out = UINT64_MAX); uint64_t get_last_block_of_type(bool looking_for_pos, const test_generator::blockchain_vector& blck_chain); + +bool decode_output_amount_and_asset_id(const currency::account_base& acc, const currency::transaction& tx, size_t output_index, uint64_t &amount, crypto::public_key* p_asset_id = nullptr); +uint64_t decode_native_output_amount_or_throw(const currency::account_base& acc, const currency::transaction& tx, size_t output_index); + bool generate_pos_block_with_given_coinstake(test_generator& generator, const std::vector &events, const currency::account_base& miner, const currency::block& prev_block, const currency::transaction& stake_tx, size_t stake_output_idx, currency::block& result, uint64_t stake_output_gidx = UINT64_MAX); bool check_ring_signature_at_gen_time(const std::vector& events, const crypto::hash& last_block_id, const currency::txin_to_key& in_t_k, const crypto::hash& hash_for_sig, const std::vector &sig); @@ -1021,11 +1025,18 @@ inline void count_ref_by_id_and_gindex_refs_for_tx_inputs(const currency::transa refs_by_gindex = 0; for (auto& in : tx.vin) { - if (in.type() != typeid(currency::txin_to_key)) + const currency::referring_input* p_ri = nullptr; + VARIANT_SWITCH_BEGIN(in) + VARIANT_CASE_CONST(currency::txin_to_key, intk) + p_ri = &intk; + VARIANT_CASE_CONST(currency::txin_zc_input, inzc) + p_ri = &inzc; + VARIANT_SWITCH_END() + + if (!p_ri) continue; - const currency::txin_to_key& in2key = boost::get(in); - for (auto& ko : in2key.key_offsets) + for (auto& ko : p_ri->key_offsets) { if (ko.type() == typeid(currency::ref_by_id)) ++refs_by_id; From 7da72fcc899d81a69654710ce82acb196328f317 Mon Sep 17 00:00:00 2001 From: sowle Date: Sat, 1 Jun 2024 21:15:42 +0200 Subject: [PATCH 07/53] chaingen: pos_block_builder adapted for HF4 and now can generate correct Zarcanum PoS blocks --- tests/core_tests/pos_block_builder.cpp | 70 +++++++++++++++++++++++--- tests/core_tests/pos_block_builder.h | 2 +- 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/tests/core_tests/pos_block_builder.cpp b/tests/core_tests/pos_block_builder.cpp index c96575b1..8d394d0e 100644 --- a/tests/core_tests/pos_block_builder.cpp +++ b/tests/core_tests/pos_block_builder.cpp @@ -167,10 +167,10 @@ void pos_block_builder::step4_generate_coinbase_tx(size_t median_size, // generate miner tx using incorrect current_block_size only for size estimation uint64_t block_reward_without_fee = 0; - uint64_t block_reward = 0; + m_block_reward = 0; size_t estimated_block_size = m_txs_total_size; bool r = construct_miner_tx(m_height, median_size, already_generated_coins, estimated_block_size, m_total_fee, - reward_receiver_address, stakeholder_address, m_block.miner_tx, block_reward_without_fee, block_reward, tx_version, extra_nonce, max_outs, true, pe, &m_miner_tx_tgc, tx_one_time_key_to_use); + reward_receiver_address, stakeholder_address, m_block.miner_tx, block_reward_without_fee, m_block_reward, tx_version, extra_nonce, max_outs, true, pe, &m_miner_tx_tgc, tx_one_time_key_to_use); CHECK_AND_ASSERT_THROW_MES(r, "construct_miner_tx failed"); estimated_block_size = m_txs_total_size + get_object_blobsize(m_block.miner_tx); @@ -178,7 +178,7 @@ void pos_block_builder::step4_generate_coinbase_tx(size_t median_size, for (size_t try_count = 0; try_count != 10; ++try_count) { r = construct_miner_tx(m_height, median_size, already_generated_coins, estimated_block_size, m_total_fee, - reward_receiver_address, stakeholder_address, m_block.miner_tx, block_reward_without_fee, block_reward, tx_version, extra_nonce, max_outs, true, pe, &m_miner_tx_tgc, tx_one_time_key_to_use); + reward_receiver_address, stakeholder_address, m_block.miner_tx, block_reward_without_fee, m_block_reward, tx_version, extra_nonce, max_outs, true, pe, &m_miner_tx_tgc, tx_one_time_key_to_use); CHECK_AND_ASSERT_THROW_MES(r, "construct_homemade_pos_miner_tx failed"); cumulative_size = m_txs_total_size + get_object_blobsize(m_block.miner_tx); @@ -230,13 +230,71 @@ void pos_block_builder::step5_sign(const currency::tx_source_entry& se, const cu ring.emplace_back(el.stealth_address, el.amount_commitment, el.blinded_asset_id, el.concealing_point); } - crypto::hash tx_hash_for_sig = get_block_hash(m_block); + crypto::point_t stake_out_blinded_asset_id_pt = currency::native_coin_asset_id_pt + se.real_out_asset_id_blinding_mask * crypto::c_point_X; + + crypto::hash hash_for_zarcanum_sig = get_block_hash(m_block); +#ifndef NDEBUG + { + crypto::point_t source_amount_commitment = crypto::c_scalar_1div8 * se.amount * stake_out_blinded_asset_id_pt + crypto::c_scalar_1div8 * se.real_out_amount_blinding_mask * crypto::c_point_G; + CHECK_AND_ASSERT_THROW_MES(se.outputs[se.real_output].amount_commitment == source_amount_commitment.to_public_key(), "real output amount commitment check failed"); + CHECK_AND_ASSERT_THROW_MES(ring[prepared_real_out_index].amount_commitment == se.outputs[se.real_output].amount_commitment, "ring secret member doesn't match with the stake output"); + CHECK_AND_ASSERT_THROW_MES(m_context.stake_amount == se.amount, "stake_amount missmatch"); + } +#endif + + CHECK_AND_ASSERT_THROW_MES(m_miner_tx_tgc.pseudo_out_amount_blinding_masks_sum.is_zero(), "pseudo_out_amount_blinding_masks_sum is nonzero"); // it should be zero because there's only one input (stake), and thus one pseudo out + crypto::scalar_t pseudo_out_amount_blinding_mask = m_miner_tx_tgc.amount_blinding_masks_sum; // sum of outputs' amount blinding masks + + //LOG_PRINT_YELLOW(std::setw(42) << std::left << "pseudo_out_amount_blinding_mask : " << pseudo_out_amount_blinding_mask, LOG_LEVEL_0); + //LOG_PRINT_YELLOW(std::setw(42) << std::left << "m_miner_tx_tgc.amount_blinding_masks[0] : " << m_miner_tx_tgc.amount_blinding_masks[0], LOG_LEVEL_0); + + m_miner_tx_tgc.pseudo_outs_blinded_asset_ids.emplace_back(currency::native_coin_asset_id_pt); // for Zarcanum stake inputs pseudo outputs commitments has explicit native asset id + m_miner_tx_tgc.pseudo_outs_plus_real_out_blinding_masks.emplace_back(0); + m_miner_tx_tgc.real_zc_ins_asset_ids.emplace_back(se.asset_id); + // TODO @#@# [architecture] the same value is calculated in zarcanum_generate_proof(), consider an impovement + m_miner_tx_tgc.pseudo_out_amount_commitments_sum += m_context.stake_amount * stake_out_blinded_asset_id_pt + pseudo_out_amount_blinding_mask * crypto::c_point_G; + m_miner_tx_tgc.real_in_asset_id_blinding_mask_x_amount_sum += se.real_out_asset_id_blinding_mask * m_context.stake_amount; + + //LOG_PRINT_YELLOW(std::setw(42) << std::left << "pseudo_out_amount_commitments_sum : " << m_miner_tx_tgc.pseudo_out_amount_commitments_sum, LOG_LEVEL_0); + uint8_t err = 0; - r = crypto::zarcanum_generate_proof(tx_hash_for_sig, m_context.kernel_hash, ring, m_context.last_pow_block_id_hashed, m_context.sk.kimage, - secret_x, m_context.secret_q, prepared_real_out_index,m_context.stake_amount, se.real_out_asset_id_blinding_mask, m_context.stake_out_amount_blinding_mask, -m_miner_tx_tgc.amount_blinding_masks_sum, + r = crypto::zarcanum_generate_proof(hash_for_zarcanum_sig, m_context.kernel_hash, ring, m_context.last_pow_block_id_hashed, m_context.sk.kimage, + secret_x, m_context.secret_q, prepared_real_out_index, m_context.stake_amount, se.real_out_asset_id_blinding_mask, m_context.stake_out_amount_blinding_mask, pseudo_out_amount_blinding_mask, static_cast(sig), &err); CHECK_AND_ASSERT_THROW_MES(r, "zarcanum_generate_proof failed, err: " << (int)err); + + // + // The miner tx prefix should be sealed by now, and the tx hash should be defined. + // Any changes made below should only affect the signatures/proofs and should not impact the prefix hash calculation. + // + crypto::hash miner_tx_id = get_transaction_hash(m_block.miner_tx); + + // proofs for miner_tx + + // asset surjection proof + currency::zc_asset_surjection_proof asp{}; + r = generate_asset_surjection_proof(miner_tx_id, false, m_miner_tx_tgc, asp); // has_non_zc_inputs == false because after the HF4 PoS mining is only allowed for ZC stakes inputs + CHECK_AND_ASSERT_THROW_MES(r, "generete_asset_surjection_proof failed"); + m_block.miner_tx.proofs.emplace_back(std::move(asp)); + + // range proofs + currency::zc_outs_range_proof range_proofs{}; + r = generate_zc_outs_range_proof(miner_tx_id, 0, m_miner_tx_tgc, m_block.miner_tx.vout, range_proofs); + CHECK_AND_ASSERT_THROW_MES(r, "Failed to generate zc_outs_range_proof()"); + m_block.miner_tx.proofs.emplace_back(std::move(range_proofs)); + + // balance proof + currency::zc_balance_proof balance_proof{}; + r = generate_tx_balance_proof(m_block.miner_tx, miner_tx_id, m_miner_tx_tgc, m_block_reward, balance_proof); + CHECK_AND_ASSERT_THROW_MES(r, "generate_tx_balance_proof failed"); + m_block.miner_tx.proofs.emplace_back(std::move(balance_proof)); + + //err = 0; + //r = crypto::zarcanum_verify_proof(hash_for_zarcanum_sig, m_context.kernel_hash, ring, m_context.last_pow_block_id_hashed, m_context.sk.kimage, m_context.basic_diff, sig, &err); + //CHECK_AND_ASSERT_THROW_MES(r, "zarcanum_verify_proof failed, err: " << (int)err); + //r = check_tx_balance(m_block.miner_tx, miner_tx_id, m_block_reward); + //CHECK_AND_ASSERT_THROW_MES(r, "check_tx_balance failed"); } else { diff --git a/tests/core_tests/pos_block_builder.h b/tests/core_tests/pos_block_builder.h index 46c49900..fdf7a297 100644 --- a/tests/core_tests/pos_block_builder.h +++ b/tests/core_tests/pos_block_builder.h @@ -77,7 +77,7 @@ struct pos_block_builder //currency::stake_kernel m_stake_kernel {}; size_t m_height = 0; size_t m_pos_stake_output_gindex = 0; - //uint64_t m_pos_stake_amount = 0; + uint64_t m_block_reward = 0; currency::tx_generation_context m_miner_tx_tgc {}; currency::pos_mining_context m_context {}; From 66fd58b8ee64a2d0fb56a39c070134c745a73dd5 Mon Sep 17 00:00:00 2001 From: sowle Date: Sat, 1 Jun 2024 21:20:58 +0200 Subject: [PATCH 08/53] coretests: many altchain tests adapted for post-HF4: pos_altblocks_validation chain_switching_when_gindex_spent_in_both_chains alt_blocks_validation_and_same_new_amount_in_two_txs alt_blocks_with_the_same_txs chain_switching_when_out_spent_in_alt_chain_mixin chain_switching_when_out_spent_in_alt_chain_ref_id --- tests/core_tests/chain_switch_1.cpp | 109 +++++++++++++++++------ tests/core_tests/chaingen_main.cpp | 12 +-- tests/core_tests/pos_validation.cpp | 130 ++++++++++++++++++---------- 3 files changed, 169 insertions(+), 82 deletions(-) diff --git a/tests/core_tests/chain_switch_1.cpp b/tests/core_tests/chain_switch_1.cpp index a579515f..2c830dd6 100644 --- a/tests/core_tests/chain_switch_1.cpp +++ b/tests/core_tests/chain_switch_1.cpp @@ -422,6 +422,15 @@ bool chain_switching_when_gindex_spent_in_both_chains::generate(std::vector sources; - r = fill_tx_sources(sources, events, blk_1r, miner_acc.get_keys(), new_amount + TESTS_DEFAULT_FEE, 0); + r = fill_tx_sources(sources, events, blk_1r, miner_acc.get_keys(), new_amount + 2*TESTS_DEFAULT_FEE, 0); CHECK_AND_ASSERT_MES(r, false, "fill_tx_sources failed"); std::vector destinations; - destinations.push_back(tx_destination_entry(new_amount, miner_acc.get_public_address())); // no cashback, just payment + destinations.push_back(tx_destination_entry(new_amount, miner_acc.get_public_address())); + destinations.push_back(tx_destination_entry(TESTS_DEFAULT_FEE, miner_acc.get_public_address())); //just to make two outputs (to please HF4 rules) transaction tx_1 = AUTO_VAL_INIT(tx_1); uint64_t tx_version = get_tx_version(get_block_height(blk_3), m_hardforks); r = construct_tx(miner_acc.get_keys(), sources, destinations, empty_attachment, tx_1, tx_version, 0); CHECK_AND_ASSERT_MES(r, false, "construct_tx failed"); - events.push_back(tx_1); + ADD_CUSTOM_EVENT(events, tx_1); // second tx sources.clear(); - r = fill_tx_sources(sources, events, blk_1r, miner_acc.get_keys(), new_amount + TESTS_DEFAULT_FEE, 0, sources); + r = fill_tx_sources(sources, events, blk_1r, miner_acc.get_keys(), new_amount + 2*TESTS_DEFAULT_FEE, 0, sources); CHECK_AND_ASSERT_MES(r, false, "fill_tx_sources failed"); transaction tx_2 = AUTO_VAL_INIT(tx_2); // use the same destinations tx_version = get_tx_version(get_block_height(blk_3), m_hardforks); r = construct_tx(miner_acc.get_keys(), sources, destinations, empty_attachment, tx_2, tx_version, 0); CHECK_AND_ASSERT_MES(r, false, "construct_tx failed"); - events.push_back(tx_2); + ADD_CUSTOM_EVENT(events, tx_2); // make an alt block with these txs MAKE_NEXT_BLOCK_TX_LIST(events, blk_3a, blk_2a, miner_acc, std::list({ tx_1, tx_2 })); @@ -565,10 +577,19 @@ alt_blocks_with_the_same_txs::alt_blocks_with_the_same_txs() bool alt_blocks_with_the_same_txs::generate(std::vector& events) const { - // Test idea: check that many two alt blocks having the same tx are correctly handled with respect to is_tx_related_to_altblock() + // Test idea: check that two alt blocks having the same tx are correctly handled with respect to is_tx_related_to_altblock() GENERATE_ACCOUNT(miner_acc); MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time()); + DO_CALLBACK(events, "configure_core"); // necessary to set m_hardforks + if (m_hardforks.is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, 2)) + { + // HF4 requires tests_random_split_strategy (for 2 outputs minimum) + test_gentime_settings tgts = generator.get_test_gentime_settings(); + tgts.split_strategy = tests_random_split_strategy; + generator.set_test_gentime_settings(tgts); + } + MAKE_NEXT_BLOCK(events, blk_1, blk_0, miner_acc); REWIND_BLOCKS_N(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1); @@ -634,15 +655,24 @@ bool chain_switching_when_out_spent_in_alt_chain_mixin::generate(std::vector& events) const { - random_state_test_restorer::reset_random(0); // to make the test deterministic + //random_state_test_restorer::reset_random(0); // to make the test deterministic uint64_t ts = 1450000000; test_core_time::adjust(ts); @@ -701,15 +735,24 @@ bool chain_switching_when_out_spent_in_alt_chain_ref_id::generate(std::vector destinations; - destinations.push_back(tx_destination_entry(MK_TEST_COINS(4), bob_acc.get_public_address())); + destinations.push_back(tx_destination_entry(MK_TEST_COINS(3), bob_acc.get_public_address())); + destinations.push_back(tx_destination_entry(MK_TEST_COINS(1), bob_acc.get_public_address())); size_t nmix = 3; - r = construct_tx_to_key(m_hardforks, events, tx_1, blk_2a, alice_acc, destinations, TESTS_DEFAULT_FEE, nmix, 0, empty_extra, empty_attachment, true, true, true); + r = construct_tx_to_key(m_hardforks, events, tx_1, blk_2ar, alice_acc, destinations, TESTS_DEFAULT_FEE, nmix, 0, empty_extra, empty_attachment, true, true, true /* use_ref_by_id */); CHECK_AND_ASSERT_MES(r, false, "construct_tx_to_key failed"); // make sure tx_1 really use ref_by_id @@ -748,17 +796,22 @@ bool chain_switching_when_out_spent_in_alt_chain_ref_id::generate(std::vector& events) @@ -871,23 +871,26 @@ bool pos_altblocks_validation::generate(std::vector& events) c std::list miner_acc_lst(1, miner_acc); MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time()); DO_CALLBACK(events, "configure_core"); - MAKE_NEXT_BLOCK(events, blk_1, blk_0, alice_acc); + REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + MAKE_NEXT_BLOCK(events, blk_1, blk_0r, alice_acc); REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); + bool HF4_active = m_hardforks.is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, get_block_height(blk_1r) + 1); + MAKE_NEXT_BLOCK(events, blk_2, blk_1r, miner_acc); const transaction& stake_tx = blk_1.miner_tx; - uint64_t alice_money = get_outs_money_amount(stake_tx); uint64_t stake_tx_out_id = 0; - // select stake_tx_out_id as an output with the biggest amount - for (size_t i = 1; i < stake_tx.vout.size(); ++i) - { - if (boost::get(stake_tx.vout[i]).amount >boost::get( stake_tx.vout[stake_tx_out_id]).amount) - stake_tx_out_id = i; - } + uint64_t alice_money = decode_native_output_amount_or_throw(alice_acc, blk_1.miner_tx, stake_tx_out_id); + //// select stake_tx_out_id as an output with the biggest amount + //for (size_t i = 1; i < stake_tx.vout.size(); ++i) + //{ + // if (boost::get(stake_tx.vout[i]).amount > boost::get( stake_tx.vout[stake_tx_out_id]).amount) + // stake_tx_out_id = i; + //} MAKE_TX_FEE(events, tx_0, alice_acc, alice_acc, alice_money - TESTS_DEFAULT_FEE * 17, TESTS_DEFAULT_FEE * 17, blk_2); // tx_0 transfers all Alice's money, so it effectevily spends all outputs in stake_ts, make sure it does - CHECK_AND_ASSERT_MES(tx_0.vin.size() == stake_tx.vout.size(), false, "probably, tx_0 doesn't spend all Alice's money as expected, tx_0.vin.size()=" << tx_0.vin.size() << ", stake_tx.vout.size()=" << stake_tx.vout.size()); + //CHECK_AND_ASSERT_MES(tx_0.vin.size() == stake_tx.vout.size(), false, "probably, tx_0 doesn't spend all Alice's money as expected, tx_0.vin.size()=" << tx_0.vin.size() << ", stake_tx.vout.size()=" << stake_tx.vout.size()); MAKE_NEXT_BLOCK_TX1(events, blk_3, blk_2, miner_acc, tx_0); @@ -900,12 +903,13 @@ bool pos_altblocks_validation::generate(std::vector& events) c REWIND_BLOCKS_N_WITH_TIME(events, blk_3r, blk_3, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); MAKE_NEXT_POS_BLOCK(events, blk_4, blk_3r, miner_acc, miner_acc_lst); MAKE_NEXT_BLOCK(events, blk_5, blk_4, miner_acc); + MAKE_NEXT_POS_BLOCK(events, blk_6, blk_5, miner_acc, miner_acc_lst); - // 0 1 11 12 13 23 24 25 <- height + // 0 11 21 22 23 33 34 35 36 <- height // // +------- blk_1 mined by Alice // | - // (0 )- (1 )-...(1r)- (2 )- (3 )-...(3r)- (4 )- (5 )- <- main chain + // (0 )- (1 )-...(1r)- (2 )- (3 )-...(3r)- (4 )- (5 )- (6 )- <- main chain // | tx_0 // +---<<---uses-blk_1-out--+ @@ -915,38 +919,60 @@ bool pos_altblocks_validation::generate(std::vector& events) c block blk_2a = AUTO_VAL_INIT(blk_2a); r = generate_pos_block_with_given_coinstake(generator, events, alice_acc, blk_1r, stake_tx, stake_tx_out_id, blk_2a); CHECK_AND_ASSERT_MES(r, false, "generate_pos_block_with_given_coinstake failed"); - events.push_back(blk_2a); + ADD_CUSTOM_EVENT(events, blk_2a); CHECK_AND_ASSERT_MES(generator.add_block_info(blk_2a, std::list()), false, "add_block_info failed"); - // 0 1 11 12 13 23 24 25 <- height + // 0 11 21 22 23 33 34 35 36 <- height // // +-----------------------+ - // | tx_0 tx_0 spends all outputs in blk_1 (main chain) - // (0 )- (1 )-...(1r)- (2 )- (3 )-...(3r)- (4 )- (5 )- <- main chain + // | tx_0 tx_0 spends all outputs in blk_1 (main chain) + // (0 )- (1 )-...(1r)- (2 )- (3 )-...(3r)- (4 )- (5 )- (6 )- <- main chain // | \ - // | \- (2a)- <- alt chain - // +--------------+ PoS block 2a uses stake already spent in main chain + // | \- (2a)- <- alt chain + // +--------------+ PoS block 2a uses stake already spent in main chain - // Case 2 (should fail) + // Case 2a (should fail) // alt PoS block (blk_3a) refers in its coinstake to an output (stake_tx_out_id) already spent in this alt chain (in blk_2a) block blk_3a = AUTO_VAL_INIT(blk_3a); r = generate_pos_block_with_given_coinstake(generator, events, alice_acc, blk_2a, stake_tx, stake_tx_out_id, blk_3a); CHECK_AND_ASSERT_MES(r, false, "generate_pos_block_with_given_coinstake failed"); DO_CALLBACK(events, "mark_invalid_block"); - events.push_back(blk_3a); + ADD_CUSTOM_EVENT(events, blk_3a); - // 0 1 11 12 13 23 24 25 <- height + // 0 11 21 22 23 33 34 35 36 <- height // // +-----------------------+ - // | tx_0 tx_0 spends all outputs in blk_1 (main chain) - // (0 )- (1 )-...(1r)- (2 )- (3 )-...(3r)- (4 )- (5 )- <- main chain + // | tx_0 tx_0 spends all outputs in blk_1 (main chain) + // (0 )- (1 )-...(1r)- (2 )- (3 )-...(3r)- (4 )- (5 )- (6 )- <- main chain // || \ - // || \- (2a)- #3a#- <- alt chain - // |+--------------+ | PoS block 2a uses stake already spent in main chain (okay) - // +-----------------------+ PoS block 3a uses stake already spent in current alt chain (fail) + // || \- (2a)- #3a#- <- alt chain + // |+--------------+ | PoS block 2a uses stake already spent in main chain (okay) + // +-----------------------+ PoS block 3a uses stake already spent in current alt chain (fail) + // Case 2b (should fail) + // alt PoS block (blk_3aa) has invalid signature + block blk_3aa{}; + r = generate_pos_block_with_given_coinstake(generator, events, miner_acc, blk_2a, blk_0r.miner_tx, 0, blk_3aa); + CHECK_AND_ASSERT_MES(r, false, "generate_pos_block_with_given_coinstake failed"); + if (HF4_active) + boost::get(blk_3aa.miner_tx.signatures[0]).y0.m_u64[1] = 5; // invalidate signature + else + boost::get(blk_3aa.miner_tx.signatures[0]).s[0].c.data[5] = 7; // invalidate signature + DO_CALLBACK(events, "mark_invalid_block"); + ADD_CUSTOM_EVENT(events, blk_3aa); + + // 0 11 21 22 23 33 34 35 36 <- height + // + // +-----------------------+ + // | tx_0 tx_0 spends all outputs in blk_1 (main chain) + // (0 )- (1 )-...(1r)- (2 )- (3 )-...(3r)- (4 )- (5 )- (6 )- <- main chain + // || \ + // || \- (2a)- #3aa#- <- alt chain + // |+--------------+ | PoS block 2a uses stake already spent in main chain (okay) + // +-----------------------+ PoS block 3aa has incorrect signature (fail) + REWIND_BLOCKS_N_WITH_TIME(events, blk_2br, blk_2a, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW); // Case 3 (should pass) @@ -954,55 +980,63 @@ bool pos_altblocks_validation::generate(std::vector& events) c block blk_3b = AUTO_VAL_INIT(blk_3b); r = generate_pos_block_with_given_coinstake(generator, events, alice_acc, blk_2br, blk_2a.miner_tx, 0, blk_3b); CHECK_AND_ASSERT_MES(r, false, "generate_pos_block_with_given_coinstake failed"); - events.push_back(blk_3b); + ADD_CUSTOM_EVENT(events, blk_3b); CHECK_AND_ASSERT_MES(generator.add_block_info(blk_3b, std::list()), false, "add_block_info failed"); - // 0 1 11 12 13 22 23 24 25 <- height + // 0 11 21 22 23 33 34 35 36 <- height // // +-----------------------+ - // | tx_0 tx_0 spends all outputs in blk_1 (main chain) - // (0 )- (1 )-...(1r)- (2 )- (3 )- ........ (3r)- (4 )- (5 )- <- main chain + // | tx_0 tx_0 spends all outputs in blk_1 (main chain) + // (0 )- (1 )-...(1r)- (2 )- (3 )- ........ (3r)- (4 )- (5 )- (6 )- <- main chain // || \ - // || \- (2a)- #3a#- <- alt chain - // |+--------------+ \ | PoS block 2a uses stake already spent in main chain (okay) - // +---------------|-------+ PoS block 3a uses stake already spent in current alt chain (fail) + // || \- (2a)- #3a#- <- alt chain + // |+--------------+ \ | PoS block 2a uses stake already spent in main chain (okay) + // +---------------|-------+ PoS block 3a uses stake already spent in current alt chain (fail) // | \ - // | \ ...... (2br)- (3b)- <- alt chain + // | \ ...... (2br)- (3b)- <- alt chain // | | - // +-----------------------+ PoS block 3b uses as stake an output, created in current alt chain (2a) + // +-----------------------+ PoS block 3b uses as stake an output, created in current alt chain (2a) // Case 4 (should fail) // alt PoS block (blk_4b) in its coinstake refers to an output (tx_0) that appeared in the main chain (blk_3) above split height block blk_4b = AUTO_VAL_INIT(blk_4b); r = generate_pos_block_with_given_coinstake(generator, events, alice_acc, blk_3b, tx_0, tx_0_some_output_idx, blk_4b, tx_0_some_output_gindex); - CHECK_AND_ASSERT_MES(r, false, "generate_pos_block_with_given_coinstake failed"); - DO_CALLBACK(events, "mark_invalid_block"); - events.push_back(blk_4b); + if (HF4_active) + { + CHECK_AND_ASSERT_MES(!r, false, "generate_pos_block_with_given_coinstake not failed as expected"); + } + else + { + CHECK_AND_ASSERT_MES(r, false, "generate_pos_block_with_given_coinstake failed"); + DO_CALLBACK(events, "mark_invalid_block"); + ADD_CUSTOM_EVENT(events, blk_4b); + } - // 0 1 11 12 13 22 23 24 25 <- height + // 0 11 21 22 23 33 34 35 36 <- height // +------------------+ // +-----------------------+ | | - // | tx_0 | tx_0 spends all outputs in blk_1 (main chain) - // (0 )- (1 )-...(1r)- (2 )- (3 )- ........ (3r)- (4 )- (5 )- <- main chain + // | tx_0 | tx_0 spends all outputs in blk_1 (main chain) + // (0 )- (1 )-...(1r)- (2 )- (3 )- ........ (3r)- (4 )- (5 )- (6 )- <- main chain // || \ | - // || \- (2a)- #3a#- | <- alt chain - // |+--------------+ \ | \ PoS block 2a uses stake already spent in main chain (okay) - // +---------------|-------+ \ PoS block 3a uses stake already spent in current alt chain (fail) + // || \- (2a)- #3a#- | <- alt chain + // |+--------------+ \ | \ PoS block 2a uses stake already spent in main chain (okay) + // +---------------|-------+ \ PoS block 3a uses stake already spent in current alt chain (fail) // | \ \ - // | \ ...... (2br)- (3b)- #4b# <- alt chain + // | \ ...... (2br)- (3b)- #4b# <- alt chain // | | - // +-----------------------+ PoS block 3b uses as stake an output, created in current alt chain (2a) + // +-----------------------+ PoS block 3b uses as stake an output, created in current alt chain (2a) - DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(get_block_height(blk_5), get_block_hash(blk_5))); + DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(get_block_height(blk_6), get_block_hash(blk_6))); // Final check: switch the chains MAKE_NEXT_BLOCK(events, blk_4c, blk_3b, miner_acc); MAKE_NEXT_BLOCK(events, blk_5c, blk_4c, miner_acc); MAKE_NEXT_BLOCK(events, blk_6c, blk_5c, miner_acc); + MAKE_NEXT_BLOCK(events, blk_7c, blk_6c, miner_acc); - DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(get_block_height(blk_6c), get_block_hash(blk_6c))); + DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(get_block_height(blk_7c), get_block_hash(blk_7c))); size_t txs_count = 1; DO_CALLBACK_PARAMS(events, "check_tx_pool_count", txs_count); // tx_0 should left in the pool From dd7d1d31096b333603397b1f7651e381932712ab Mon Sep 17 00:00:00 2001 From: sowle Date: Sat, 1 Jun 2024 22:06:21 +0200 Subject: [PATCH 09/53] greatly refactored alt block verification and improved it for post-HF4 era (now all updated tests should pass) --- src/crypto/clsag.h | 5 +- src/currency_core/blockchain_storage.cpp | 373 ++++++++++------------- src/currency_core/blockchain_storage.h | 52 ++-- 3 files changed, 197 insertions(+), 233 deletions(-) diff --git a/src/crypto/clsag.h b/src/crypto/clsag.h index da969d8a..924af50d 100644 --- a/src/crypto/clsag.h +++ b/src/crypto/clsag.h @@ -50,8 +50,9 @@ namespace crypto // - // Disclaimer: extensions to the CLSAG implemented below are non-standard and are in proof-of-concept state. - // They shouldn't be used in production code until formal security proofs are done and (ideally) the code is peer-reviewed. + // d/v-CLSAG implementation + // See the whitepaper: https://hyle-team.github.io/docs/zano/dv-CLSAG-extension/dv-CLSAG-extension.pdf + // Review by Cypher Stack: https://github.com/cypherstack/zano-clsag-review // -- sowle // diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 3414f213..c33161dd 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2024 Zano Project // Copyright (c) 2014-2018 The Louisdor Project // Copyright (c) 2012-2013 The Cryptonote developers // Copyright (c) 2012-2013 The Boolberry developers @@ -1917,6 +1917,10 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto:: // } + abei.difficulty = current_diff; + wide_difficulty_type cumulative_diff_delta = 0; + abei.cumulative_diff_adjusted = alt_chain.size() ? it_prev->second.cumulative_diff_adjusted : m_db_blocks[*ptr_main_prev]->cumulative_diff_adjusted; + std::unordered_set alt_block_keyimages; uint64_t ki_lookup_total = 0; if (!validate_alt_block_txs(b, id, alt_block_keyimages, abei, alt_chain, connection_height, ki_lookup_total)) @@ -1925,10 +1929,6 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto:: bvc.m_verification_failed = true; return false; } - - abei.difficulty = current_diff; - wide_difficulty_type cumulative_diff_delta = 0; - abei.cumulative_diff_adjusted = alt_chain.size() ? it_prev->second.cumulative_diff_adjusted : m_db_blocks[*ptr_main_prev]->cumulative_diff_adjusted; if (pos_block) cumulative_diff_delta = get_adjusted_cumulative_difficulty_for_next_alt_pos(alt_chain, abei.height, current_diff, connection_height); @@ -7379,9 +7379,11 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, const crypto::hash& bl_id, const crypto::hash& input_tx_hash, size_t input_index, - uint64_t split_height, - const alt_chain_type& alt_chain, - const std::unordered_set& alt_chain_block_ids, + uint64_t split_height, + const alt_chain_type& alt_chain, + const std::unordered_set& alt_chain_block_ids, + const uint64_t pos_block_timestamp, + const wide_difficulty_type& pos_difficulty, uint64_t& ki_lookuptime, uint64_t* p_max_related_block_height /* = nullptr */) const { @@ -7458,41 +7460,55 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, std::vector abs_key_offsets = relative_output_offsets_to_absolute(input_key_offsets); CHECK_AND_ASSERT_MES(abs_key_offsets.size() > 0 && abs_key_offsets.size() == input_key_offsets.size(), false, "internal error: abs_key_offsets.size()==" << abs_key_offsets.size() << ", input_key_offsets.size()==" << input_key_offsets.size()); - // eventually we should found all public keys for all outputs this input refers to, for checking ring signature - std::vector pub_keys(abs_key_offsets.size(), null_pkey); // - // let's try to resolve references and populate pub keys container for check_tokey_input() + // let's try to resolve references and populate the ring for ring signature check // uint64_t global_outs_for_amount = 0; //figure out if this amount touched alt_chain amount's index and if it is, get bool amount_touched_altchain = false; - //auto abg_it = abei.gindex_lookup_table.find(input_to_key.amount); - //if (abg_it == abei.gindex_lookup_table.end()) - - if (!alt_chain.empty()) - { - auto abg_it = alt_chain.back()->second.gindex_lookup_table.find(input_amount); - if (input_amount != 0 /* <-- TODO @#@# remove this condition after ZC outs support is implemented*/ && abg_it != alt_chain.back()->second.gindex_lookup_table.end()) - { - amount_touched_altchain = true; - // local gindex lookup table contains last used gindex, so we can't get total number of outs - // just skip setting global_outs_for_amount - } - else - { - //quite easy, - global_outs_for_amount = m_db_outputs.get_item_size(input_amount); - } - } + if (!alt_chain.empty() && alt_chain.back()->second.gindex_lookup_table.count(input_amount) != 0) + amount_touched_altchain = true; // local gindex lookup table contains last used gindex, so we can't get total number of outs, just skip setting global_outs_for_amount else - { - //quite easy, global_outs_for_amount = m_db_outputs.get_item_size(input_amount); - } - - CHECK_AND_ASSERT_MES(pub_keys.size() == abs_key_offsets.size(), false, "pub_keys.size()==" << pub_keys.size() << " != abs_key_offsets.size()==" << abs_key_offsets.size()); // just a little bit of paranoia - std::vector pub_key_pointers; + + bool pos_miner_tx = is_pos_miner_tx(input_tx); + + // eventually we should found all required public keys for all outputs this input refers to, because it's required for ring signature check + std::vector pub_keys(abs_key_offsets.size(), null_pkey); // old bare outputs + std::vector pub_key_pointers; // old bare outputs (pointers) + vector zc_input_ring; // ZC outputs + vector zarcanum_input_ring; // Zarcanum outputs + + auto add_output_to_the_ring = [&](const tx_out_v& out_v, size_t index, uint64_t top_minus_source_height) -> bool { + VARIANT_SWITCH_BEGIN(out_v) + VARIANT_CASE_CONST(tx_out_bare, bo) + { + VARIANT_SWITCH_BEGIN(bo.target) + VARIANT_CASE_CONST(txout_to_key, ttk) + pub_keys[index] = ttk.key; + pub_key_pointers.push_back(&pub_keys[index]); + VARIANT_CASE_CONST(txout_htlc, out_htlc) + bool htlc_expired = out_htlc.expiration > top_minus_source_height ? false : true; + pub_keys[index] = htlc_expired ? out_htlc.pkey_refund : out_htlc.pkey_redeem; + pub_key_pointers.push_back(&pub_keys[index]); + VARIANT_CASE_OTHER() + return false; + VARIANT_SWITCH_END() + } + VARIANT_CASE_CONST(tx_out_zarcanum, zo) + { + if (pos_miner_tx) + zarcanum_input_ring.emplace_back(zo.stealth_address, zo.amount_commitment, zo.blinded_asset_id, zo.concealing_point); + else + zc_input_ring.emplace_back(zo.stealth_address, zo.amount_commitment, zo.blinded_asset_id); + } + VARIANT_CASE_OTHER() + return false; + VARIANT_SWITCH_END() + return true; + }; + uint64_t height_of_current_alt_block = alt_chain.size() ? alt_chain.back()->second.height + 1 : split_height + 1; @@ -7506,13 +7522,13 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, { uint64_t offset_gindex = boost::get(off); CHECK_AND_ASSERT_MES(amount_touched_altchain || (offset_gindex < global_outs_for_amount), false, - "invalid global output index " << offset_gindex << " for amount=" << input_amount << + "invalid global output index " << offset_gindex << " for amount " << print_money_brief(input_amount) << ", max is " << global_outs_for_amount << ", referred to by offset #" << pk_n << ", amount_touched_altchain = " << amount_touched_altchain); if (amount_touched_altchain) { - bool found_the_key = false; + bool found = false; for (auto alt_it = alt_chain.rbegin(); alt_it != alt_chain.rend(); alt_it++) { auto it_aag = (*alt_it)->second.gindex_lookup_table.find(input_amount); @@ -7528,42 +7544,25 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, //GOT IT!! //TODO: At the moment we ignore check of mix_attr against mixing to simplify alt chain check, but in future consider it for stronger validation uint64_t local_offset = offset_gindex - it_aag->second; - auto& alt_keys = (*alt_it)->second.outputs_pub_keys; - CHECK_AND_ASSERT_MES(local_offset < alt_keys[input_amount].size(), false, "Internal error: local_offset=" << local_offset << " while alt_keys[" << input_amount << " ].size()=" << alt_keys.size()); - const output_key_or_htlc_v& out_in_alt = alt_keys[input_amount][local_offset]; + auto& alt_outputs = (*alt_it)->second.outputs; + CHECK_AND_ASSERT_MES(local_offset < alt_outputs[input_amount].size(), false, "Internal error: local_offset=" << local_offset << " while alt_outputs[" << input_amount << " ].size()=" << alt_outputs.size()); + const tx_out_v& out_in_alt = alt_outputs[input_amount][local_offset]; - /* - here we do validation against compatibility of input and output type - - TxOutput | TxInput | Allowed - ---------------------------- - HTLC | HTLC | ONLY IF HTLC NOT EXPIRED - HTLC | TO_KEY | ONLY IF HTLC IS EXPIRED - TO_KEY | HTLC | NOT - TO_KEY | TO_KEY | YES - */ uint64_t height_of_source_block = (*alt_it)->second.height; CHECK_AND_ASSERT_MES(height_of_current_alt_block > height_of_source_block, false, "Intenral error: height_of_current_alt_block > height_of_source_block failed"); - bool r = is_output_allowed_for_input(out_in_alt, input_v, height_of_current_alt_block - height_of_source_block); + uint64_t top_minus_source_height = height_of_current_alt_block - height_of_source_block; + + bool r = is_output_allowed_for_input(out_in_alt, input_v, top_minus_source_height); CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); + + r = add_output_to_the_ring(out_in_alt, pk_n, top_minus_source_height); + CHECK_AND_ASSERT_MES(r, false, "offset #" << pk_n << ": add_output_to_the_ring failed"); - if (out_in_alt.type() == typeid(crypto::public_key)) - { - pk = boost::get(out_in_alt); - } - else - { - const txout_htlc& out_htlc = boost::get(out_in_alt); - bool htlc_expired = out_htlc.expiration > (height_of_current_alt_block - height_of_source_block) ? false:true; - pk = htlc_expired ? out_htlc.pkey_refund : out_htlc.pkey_redeem; - //input_v - } - pub_key_pointers.push_back(&pk); - found_the_key = true; + found = true; break; } } - if (found_the_key) + if (found) continue; //otherwise lookup in main chain index } @@ -7583,114 +7582,62 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, { uint64_t height_of_source_block = it->second.second; CHECK_AND_ASSERT_MES(height_of_current_alt_block > height_of_source_block, false, "Intenral error: height_of_current_alt_block > height_of_source_block failed"); - + uint64_t top_minus_source_height = height_of_current_alt_block - height_of_source_block; + //source tx found in altchain CHECK_AND_ASSERT_MES(it->second.first.vout.size() > out_n, false, "Internal error: out_n(" << out_n << ") >= it->second.vout.size()(" << it->second.first.vout.size() << ")"); + const tx_out_v& out_in_alt = it->second.first.vout[out_n]; - VARIANT_SWITCH_BEGIN(it->second.first.vout[out_n]); - VARIANT_CASE_CONST(tx_out_bare, o) - { - /* - here we do validation against compatibility of input and output type + r = is_output_allowed_for_input(out_in_alt, input_v, top_minus_source_height); + CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); - TxOutput | TxInput | Allowed - ---------------------------- - HTLC | HTLC | ONLY IF HTLC NOT EXPIRED - HTLC | TO_KEY | ONLY IF HTLC IS EXPIRED - TO_KEY | HTLC | NOT - TO_KEY | TO_KEY | YES - */ - txout_target_v out_target_v = o.target; - - bool r = is_output_allowed_for_input(out_target_v, input_v, height_of_current_alt_block - height_of_source_block); - CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); - if (out_target_v.type() == typeid(txout_htlc)) - { - //source is hltc out - const txout_htlc& htlc = boost::get(out_target_v); - bool htlc_expired = htlc.expiration > (height_of_current_alt_block - height_of_source_block) ? false : true; - pk = htlc_expired ? htlc.pkey_refund : htlc.pkey_redeem; - pub_key_pointers.push_back(&pk); - continue; - } - else if (out_target_v.type() == typeid(txout_to_key)) - { - //source is to_key out - pk = boost::get(out_target_v).key; - pub_key_pointers.push_back(&pk); - continue; - } - else - { - ASSERT_MES_AND_THROW("Unexpected out type for tx_in in altblock: " << out_target_v.type().name()); - } - } - VARIANT_CASE_CONST(tx_out_zarcanum, toz) - //@#@ - VARIANT_SWITCH_END(); + r = add_output_to_the_ring(out_in_alt, pk_n, top_minus_source_height); + CHECK_AND_ASSERT_MES(r, false, "offset #" << pk_n << ": add_output_to_the_ring failed"); + continue; // found in altchain, continue with the new output } - } + // lookup the output in the main chain + auto p = m_db_transactions.get(tx_id); CHECK_AND_ASSERT_MES(p != nullptr && out_n < p->tx.vout.size(), false, "can't find output #" << out_n << " for tx " << tx_id << " referred by offset #" << pk_n); + const tx_out_v& out_in_main = p->tx.vout[out_n]; - VARIANT_SWITCH_BEGIN(p->tx.vout[out_n]); - VARIANT_CASE_CONST(tx_out_bare, o) + uint64_t height_of_source_block = p->m_keeper_block_height; + CHECK_AND_ASSERT_MES(height_of_current_alt_block > height_of_source_block, false, "Intenral error: height_of_current_alt_block > height_of_source_block failed"); + uint64_t top_minus_source_height = height_of_current_alt_block - height_of_source_block; + + uint8_t mix_attr = 0; + if (get_mix_attr_from_tx_out_v(out_in_main, mix_attr)) { - auto &t = o.target; - - /* - here we do validation against compatibility of input and output type - - TxOutput | TxInput | Allowed - ---------------------------- - HTLC | HTLC | ONLY IF HTLC NOT EXPIRED - HTLC | TO_KEY | ONLY IF HTLC IS EXPIRED - TO_KEY | HTLC | NOT - TO_KEY | TO_KEY | YES - */ - uint64_t height_of_source_block = p->m_keeper_block_height; - CHECK_AND_ASSERT_MES(height_of_current_alt_block > height_of_source_block, false, "Intenral error: height_of_current_alt_block > height_of_source_block failed"); - bool r = is_output_allowed_for_input(t, input_v, height_of_current_alt_block - height_of_source_block); - CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); - - if (t.type() == typeid(txout_to_key)) - { - const txout_to_key& out_tk = boost::get(t); - pk = out_tk.key; - - bool mixattr_ok = is_mixattr_applicable_for_fake_outs_counter(p->tx.version, out_tk.mix_attr, abs_key_offsets.size() - 1, this->get_core_runtime_config()); - CHECK_AND_ASSERT_MES(mixattr_ok, false, "input offset #" << pk_n << " violates mixin restrictions: mix_attr = " << static_cast(out_tk.mix_attr) << ", input's key_offsets.size = " << abs_key_offsets.size()); - - } - else if (t.type() == typeid(txout_htlc)) - { - const txout_htlc& htlc = boost::get(t); - bool htlc_expired = htlc.expiration > (height_of_current_alt_block - height_of_source_block) ? false : true; - pk = htlc_expired ? htlc.pkey_refund : htlc.pkey_redeem; - } - - // case b4 (make sure source tx in the main chain is preceding split point, otherwise this referece is invalid) - CHECK_AND_ASSERT_MES(p->m_keeper_block_height < split_height, false, "input offset #" << pk_n << " refers to main chain tx " << tx_id << " at height " << p->m_keeper_block_height << " while split height is " << split_height); - - if (max_related_block_height < p->m_keeper_block_height) - max_related_block_height = p->m_keeper_block_height; - - // TODO: consider checking p->tx for unlock time validity as it's checked in get_output_keys_for_input_with_checks() - // make sure it was actually found - - // let's disable this check due to missing equal check in main chain validation code - //TODO: implement more strict validation with next hard fork - //CHECK_AND_ASSERT_MES(pk != null_pkey, false, "Can't determine output public key for offset " << pk_n << " in related tx: " << tx_id << ", out_n = " << out_n); - pub_key_pointers.push_back(&pk); + // having either txout_to_key or txout_zarcanum, for htlc or multisig outputs this check is not applicable + bool mixattr_ok = is_mixattr_applicable_for_fake_outs_counter(p->tx.version, mix_attr, abs_key_offsets.size() - 1, this->get_core_runtime_config()); + CHECK_AND_ASSERT_MES(mixattr_ok, false, "input offset #" << pk_n << " violates mixin restrictions: mix_attr = " << static_cast(mix_attr) << ", input's key_offsets.size = " << abs_key_offsets.size()); } - VARIANT_CASE_CONST(tx_out_zarcanum, toz) - //@#@ - VARIANT_SWITCH_END(); + + // case b4 (make sure source tx in the main chain is preceding split point, otherwise this referece is invalid) + r = p->m_keeper_block_height < split_height; + CHECK_AND_ASSERT_MES(r, false, "input offset #" << pk_n << " refers to main chain tx " << tx_id << " at height " << p->m_keeper_block_height << " while split height is " << split_height); + + r = is_output_allowed_for_input(out_in_main, input_v, top_minus_source_height); + CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); + + r = add_output_to_the_ring(out_in_main, pk_n, top_minus_source_height); + CHECK_AND_ASSERT_MES(r, false, "offset #" << pk_n << ": add_output_to_the_ring failed"); + + if (max_related_block_height < p->m_keeper_block_height) + max_related_block_height = p->m_keeper_block_height; + + // TODO: consider checking p->tx for unlock time validity as it's checked in get_output_keys_for_input_with_checks() + // make sure it was actually found + + // let's disable this check due to missing equal check in main chain validation code + //TODO: implement more strict validation with next hard fork + //CHECK_AND_ASSERT_MES(pk != null_pkey, false, "Can't determine output public key for offset " << pk_n << " in related tx: " << tx_id << ", out_n = " << out_n); } - // @#@# TODO review the following checks! + + // do input checks (attachment_info, ring signature and extra signature, etc.) VARIANT_SWITCH_BEGIN(input_v); @@ -7703,17 +7650,33 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, VARIANT_CASE_CONST(txin_zc_input, input_zc); if (is_pos_miner_tx(input_tx)) { - // TODO @#@# Special case: handling Zarcanum PoS block input + // Zarcanum signature (PoS block miner tx) + stake_kernel sk{}; + stake_modifier_type sm{}; + uint64_t last_pow_block_height = 0; + r = build_stake_modifier(sm, alt_chain, split_height, nullptr, &last_pow_block_height); + CHECK_AND_ASSERT_MES(r, false, "failed to build_stake_modifier"); + r = build_kernel(input_key_image, sk, sm, pos_block_timestamp); + CHECK_AND_ASSERT_MES(r, false, "failed to build kernel_stake"); + crypto::hash kernel_hash = crypto::cn_fast_hash(&sk, sizeof(sk)); + crypto::scalar_t last_pow_block_id_hashed = crypto::hash_helper_t::hs(CRYPTO_HDS_ZARCANUM_LAST_POW_HASH, sm.last_pow_id); + CHECK_AND_ASSERT_MES(input_tx.signatures.size() != 2, false, "input_tx.signatures has wrong size: " << input_tx.signatures.size()); + CHECK_AND_ASSERT_MES(input_tx.signatures[0].type() == typeid(zarcanum_sig), false, "input_tx.signatures[" << input_index << "] has wrong type: " << input_tx.signatures[input_index].type().name()); + const zarcanum_sig& sig = boost::get(input_tx.signatures[0]); + uint8_t err = 0; + r = crypto::zarcanum_verify_proof(bl_id, kernel_hash, zarcanum_input_ring, last_pow_block_id_hashed, input_key_image, pos_difficulty, sig, &err); + CHECK_AND_ASSERT_MES(r, false, "zarcanum_verify_proof failed: err=" << (int)err); } else { - // TODO @#@# properly handle ZC inputs! check_tx_input below isn't working because of incorrectly assembled ring - /* - uint64_t max_related_block_height = 0; - bool all_tx_ins_have_explicit_asset_ids = true; // stub for now, TODO @#@# - r = check_tx_input(input_tx, input_index, input_zc, input_tx_hash, max_related_block_height, all_tx_ins_have_explicit_asset_ids); - CHECK_AND_ASSERT_MES(r, false, "check_tx_input failed"); - */ + // ZC signature (3/2-CLSAG GGX) + crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(input_tx, input_index, input_tx_hash); + CHECK_AND_ASSERT_MES(tx_hash_for_signature != null_hash, false, "prepare_prefix_hash_for_sign failed"); + CHECK_AND_ASSERT_MES(input_index < input_tx.signatures.size(), false, "input_tx.signatures has wrong size: " << input_tx.signatures.size()); + CHECK_AND_ASSERT_MES(input_tx.signatures[input_index].type() == typeid(ZC_sig), false, "input_tx.signatures[" << input_index << "] has wrong type: " << input_tx.signatures[input_index].type().name()); + const ZC_sig& sig = boost::get(input_tx.signatures[input_index]); + bool r = crypto::verify_CLSAG_GGX(tx_hash_for_signature, zc_input_ring, sig.pseudo_out_amount_commitment, sig.pseudo_out_blinded_asset_id, input_key_image, sig.clsags_ggx); + CHECK_AND_ASSERT_MES(r, false, "verify_CLSAG_GGX failed"); } VARIANT_CASE_OTHER() LOG_ERROR("unexpected input type: " << input_v.type().name()); @@ -7739,19 +7702,26 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, return true; } //------------------------------------------------------------------ +bool blockchain_storage::is_output_allowed_for_input(const tx_out_v& out_v, const txin_v& in_v, uint64_t top_minus_source_height) const +{ + if (out_v.type() == typeid(tx_out_bare)) + { + return is_output_allowed_for_input(boost::get(out_v).target, in_v, top_minus_source_height); + } + else if (out_v.type() == typeid(tx_out_zarcanum)) + { + return is_output_allowed_for_input(boost::get(out_v), in_v); + } + else + { + LOG_ERROR("[is_output_allowed_for_input]: Wrong output type in : " << out_v.type().name()); + return false; + } + return true; +} +//------------------------------------------------------------------ bool blockchain_storage::is_output_allowed_for_input(const txout_target_v& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const { - - /* - TxOutput | TxInput | Allowed - ---------------------------- - HTLC | HTLC | ONLY IF HTLC NOT EXPIRED - HTLC | TO_KEY | ONLY IF HTLC IS EXPIRED - TO_KEY | HTLC | NOT - TO_KEY | TO_KEY | YES - */ - - if (out_v.type() == typeid(txout_to_key)) { return is_output_allowed_for_input(boost::get(out_v), in_v); @@ -7770,6 +7740,14 @@ bool blockchain_storage::is_output_allowed_for_input(const txout_target_v& out_v //------------------------------------------------------------------ bool blockchain_storage::is_output_allowed_for_input(const txout_htlc& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const { + /* + TxOutput | TxInput | Allowed + ---------------------------- + HTLC | HTLC | ONLY IF HTLC NOT EXPIRED + HTLC | TO_KEY | ONLY IF HTLC IS EXPIRED + TO_KEY | HTLC | NOT + TO_KEY | TO_KEY | YES + */ bool htlc_expired = out_v.expiration > (top_minus_source_height) ? false : true; if (!htlc_expired) { @@ -7791,21 +7769,6 @@ bool blockchain_storage::is_output_allowed_for_input(const txout_to_key& out_v, return true; } //------------------------------------------------------------------ -bool blockchain_storage::is_output_allowed_for_input(const output_key_or_htlc_v& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const -{ - if (out_v.type() == typeid(crypto::public_key)) - { - return is_output_allowed_for_input(txout_to_key(), in_v); - } - else if (out_v.type() == typeid(txout_htlc)) - { - return is_output_allowed_for_input(boost::get(out_v), in_v, top_minus_source_height); - } - else { - ASSERT_MES_AND_THROW("Unexpected type in output_key_or_htlc_v: " << out_v.type().name()); - } -} -//------------------------------------------------------------------ bool blockchain_storage::is_output_allowed_for_input(const tx_out_zarcanum& out, const txin_v& in_v) const { CHECK_AND_ASSERT_MES(in_v.type() == typeid(txin_zc_input), false, "tx_out_zarcanum can only be referenced by txin_zc_input, not by " << in_v.type().name()); @@ -7970,19 +7933,17 @@ bool blockchain_storage::update_alt_out_indexes_for_tx_in_block(const transactio abei.gindex_lookup_table[o.amount] = m_db_outputs.get_item_size(o.amount); //LOG_PRINT_MAGENTA("FIRST TOUCH: size=" << abei.gindex_lookup_table[o.amount], LOG_LEVEL_0); } - if (o.target.type() == typeid(txout_to_key)) - { - abei.outputs_pub_keys[o.amount].push_back(boost::get(o.target).key); - } - else - { - abei.outputs_pub_keys[o.amount].push_back(boost::get(o.target)); - } + abei.outputs[o.amount].emplace_back(o); //TODO: At the moment we ignore check of mix_attr again mixing to simplify alt chain check, but in future consider it for stronger validation } VARIANT_CASE_CONST(tx_out_zarcanum, toz) - //@#@ + if (abei.gindex_lookup_table.find(0) == abei.gindex_lookup_table.end()) + { + // amount was not found in altchain gindexes container, start indexing from current main chain gindex + abei.gindex_lookup_table[0] = m_db_outputs.get_item_size(0); + } + abei.outputs[0].emplace_back(toz); VARIANT_SWITCH_END(); } return true; @@ -8004,8 +7965,8 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha abei.gindex_lookup_table = alt_chain.back()->second.gindex_lookup_table; //adjust indices for next alt block entry according to emount of pubkeys in txs of prev block - auto& prev_alt_keys = alt_chain.back()->second.outputs_pub_keys; - for (auto it = prev_alt_keys.begin(); it != prev_alt_keys.end(); it++) + auto& prev_alt_outputs = alt_chain.back()->second.outputs; + for (auto it = prev_alt_outputs.cbegin(); it != prev_alt_outputs.cend(); it++) { auto it_amont_in_abs_ind = abei.gindex_lookup_table.find(it->first); CHECK_AND_ASSERT_MES(it_amont_in_abs_ind != abei.gindex_lookup_table.end(), false, "internal error: not found amount " << it->first << "in gindex_lookup_table"); @@ -8038,7 +7999,7 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha // check PoS block miner tx in a special way CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1 && b.miner_tx.vin.size() == 2, false, "invalid PoS block's miner_tx, signatures size = " << b.miner_tx.signatures.size() << ", miner_tx.vin.size() = " << b.miner_tx.vin.size()); - r = validate_alt_block_input(b.miner_tx, collected_keyimages, alt_chain_tx_ids, id, get_block_hash(b), 1, split_height, alt_chain, alt_chain_block_ids, ki_lookup, &max_related_block_height); + r = validate_alt_block_input(b.miner_tx, collected_keyimages, alt_chain_tx_ids, id, get_block_hash(b), 1, split_height, alt_chain, alt_chain_block_ids, b.timestamp, abei.difficulty, ki_lookup, &max_related_block_height); CHECK_AND_ASSERT_MES(r, false, "miner tx " << get_transaction_hash(b.miner_tx) << ": validation failed"); ki_lookup_time_total += ki_lookup; @@ -8071,7 +8032,7 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha if (tx.vin[n].type() == typeid(txin_to_key) || tx.vin[n].type() == typeid(txin_htlc) || tx.vin[n].type() == typeid(txin_zc_input)) { uint64_t ki_lookup = 0; - r = validate_alt_block_input(tx, collected_keyimages, alt_chain_tx_ids, id, tx_id, n, split_height, alt_chain, alt_chain_block_ids, ki_lookup); + r = validate_alt_block_input(tx, collected_keyimages, alt_chain_tx_ids, id, tx_id, n, split_height, alt_chain, alt_chain_block_ids, 0, 0 /* <= both are not required for normal txs*/, ki_lookup); CHECK_AND_ASSERT_MES(r, false, "tx " << tx_id << ", input #" << n << ": validation failed"); ki_lookup_time_total += ki_lookup; } diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index 489f4635..2c6e0bb5 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2024 Zano Project // Copyright (c) 2014-2018 The Louisdor Project // Copyright (c) 2012-2013 The Cryptonote developers // Copyright (c) 2012-2013 The Boolberry developers @@ -165,15 +165,13 @@ namespace currency // retrieve gindex from main chain gindex table # not outputs having given amount are present after the given height // - typedef boost::variant output_key_or_htlc_v; - struct alt_block_extended_info: public block_extended_info { // {amount -> gindex } output global index lookup table for this altblock (if an amount isn't present -- it's retreived from main outputs_container) std::map gindex_lookup_table; - // {amount -> pub_keys} map of outputs' pub_keys appeared in this alt block ( index_in_vector == output_gindex - gindex_lookup_table[output_amount] ) - std::map > outputs_pub_keys; + // {amount -> outs} map of outputs' appeared in this alt block ( index_in_vector == output_gindex - gindex_lookup_table[output_amount] ) + std::map > outputs; //date added to alt chain storage uint64_t timestamp; @@ -638,6 +636,8 @@ namespace currency uint64_t split_height, const alt_chain_type& alt_chain, const std::unordered_set& alt_chain_block_ids, + const uint64_t pos_block_timestamp, + const wide_difficulty_type& pos_difficulty, uint64_t& ki_lookuptime, uint64_t* p_max_related_block_height = nullptr) const; bool validate_alt_block_ms_input(const transaction& input_tx, @@ -703,10 +703,10 @@ namespace currency void calculate_local_gindex_lookup_table_for_height(uint64_t split_height, std::map& increments) const; void do_erase_altblock(alt_chain_container::iterator it); uint64_t get_blockchain_launch_timestamp()const; - bool is_output_allowed_for_input(const txout_target_v& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const; - bool is_output_allowed_for_input(const output_key_or_htlc_v& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const; - bool is_output_allowed_for_input(const txout_to_key& out_v, const txin_v& in_v)const; - bool is_output_allowed_for_input(const txout_htlc& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const; + bool is_output_allowed_for_input(const tx_out_v& out_v, const txin_v& in_v, uint64_t top_minus_source_height) const; + bool is_output_allowed_for_input(const txout_target_v& out_v, const txin_v& in_v, uint64_t top_minus_source_height) const; + bool is_output_allowed_for_input(const txout_to_key& out_v, const txin_v& in_v) const; + bool is_output_allowed_for_input(const txout_htlc& out_v, const txin_v& in_v, uint64_t top_minus_source_height) const; bool is_output_allowed_for_input(const tx_out_zarcanum& out, const txin_v& in_v) const; @@ -876,24 +876,26 @@ namespace currency TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output); } VARIANT_CASE_CONST(tx_out_zarcanum, out_zc) - bool r = is_output_allowed_for_input(out_zc, verified_input); - CHECK_AND_ASSERT_MES(r, false, "Input and output are incompatible"); - - r = is_mixattr_applicable_for_fake_outs_counter(tx_ptr->tx.version, out_zc.mix_attr, key_offsets.size() - 1, this->get_core_runtime_config()); - CHECK_AND_ASSERT_MES(r, false, "tx input ref #" << output_index << " violates mixin restrictions: tx.version = " << tx_ptr->tx.version << ", mix_attr = " << static_cast(out_zc.mix_attr) << ", key_offsets.size = " << key_offsets.size()); - - bool legit_output_key = validate_output_key_legit(out_zc.stealth_address); - CHECK_AND_ASSERT_MES(legit_output_key, false, "tx input ref #" << output_index << " violates public key restrictions: tx.version = " << tx_ptr->tx.version << ", outtk.key = " << out_zc.stealth_address); - - - TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output); - if (!vis.handle_output(tx_ptr->tx, validated_tx, out_zc, n)) { - size_t verified_input_index = std::find(validated_tx.vin.begin(), validated_tx.vin.end(), verified_input) - validated_tx.vin.begin(); - LOG_PRINT_RED_L0("handle_output failed for output #" << n << " in " << tx_id << " referenced by input #" << verified_input_index << " in tx " << get_transaction_hash(validated_tx)); - return false; + bool r = is_output_allowed_for_input(out_zc, verified_input); + CHECK_AND_ASSERT_MES(r, false, "Input and output are incompatible"); + + r = is_mixattr_applicable_for_fake_outs_counter(tx_ptr->tx.version, out_zc.mix_attr, key_offsets.size() - 1, this->get_core_runtime_config()); + CHECK_AND_ASSERT_MES(r, false, "tx input ref #" << output_index << " violates mixin restrictions: tx.version = " << tx_ptr->tx.version << ", mix_attr = " << static_cast(out_zc.mix_attr) << ", key_offsets.size = " << key_offsets.size()); + + bool legit_output_key = validate_output_key_legit(out_zc.stealth_address); + CHECK_AND_ASSERT_MES(legit_output_key, false, "tx input ref #" << output_index << " violates public key restrictions: tx.version = " << tx_ptr->tx.version << ", outtk.key = " << out_zc.stealth_address); + + + TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output); + if (!vis.handle_output(tx_ptr->tx, validated_tx, out_zc, n)) + { + size_t verified_input_index = std::find(validated_tx.vin.begin(), validated_tx.vin.end(), verified_input) - validated_tx.vin.begin(); + LOG_PRINT_RED_L0("handle_output failed for output #" << n << " in " << tx_id << " referenced by input #" << verified_input_index << " in tx " << get_transaction_hash(validated_tx)); + return false; + } + TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output); } - TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output); VARIANT_CASE_THROW_ON_OTHER(); VARIANT_SWITCH_END(); From 10c1f7f59a4a220508ce8f3c297017be214ba262 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Sun, 2 Jun 2024 21:11:47 +0400 Subject: [PATCH 10/53] added commands for transfer ownership over asset descripto --- src/simplewallet/simplewallet.cpp | 50 +++++++++++++++++++++++++++++++ src/simplewallet/simplewallet.h | 2 +- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index c953138f..381f5e24 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -339,6 +339,7 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("emit_asset", boost::bind(&simple_wallet::emit_asset, this, ph::_1), "emit_asset - Emmit more coins for the asset, possible only if current wallet is a maintainer for the asset"); m_cmd_binder.set_handler("burn_asset", boost::bind(&simple_wallet::burn_asset, this, ph::_1), "burn_asset - Burn coins for the asset, possible only if current wallet is a maintainer for the asset AND possess given amount of coins to burn"); m_cmd_binder.set_handler("update_asset", boost::bind(&simple_wallet::update_asset, this, ph::_1), "update_asset - Update asset descriptor's metadata, possible only if current wallet is a maintainer for the asset"); + m_cmd_binder.set_handler("transfer_asset_ownership", boost::bind(&simple_wallet::transfer_asset_ownership, this, ph::_1), "transfer_asset_ownership - Update asset descriptor's owner field, so the asset ownership is transfered to new owner"); m_cmd_binder.set_handler("add_custom_asset_id", boost::bind(&simple_wallet::add_custom_asset_id, this, ph::_1), "Approve asset id to be recognized in the wallet and returned in balances"); m_cmd_binder.set_handler("remove_custom_asset_id", boost::bind(&simple_wallet::remove_custom_asset_id, this, ph::_1), "Cancel previously made approval for asset id"); @@ -2240,6 +2241,55 @@ bool simple_wallet::update_asset(const std::vector &args) return true; } //---------------------------------------------------------------------------------------------------- +bool simple_wallet::transfer_asset_ownership(const std::vector& args) +{ + CONFIRM_WITH_PASSWORD(); + SIMPLE_WALLET_BEGIN_TRY_ENTRY(); + if (args.size() != 2) + { + fail_msg_writer() << "invalid arguments count: " << args.size() << ", expected 2"; + return true; + } + + crypto::public_key asset_id = currency::null_pkey; + bool r = epee::string_tools::parse_tpod_from_hex_string(args[0], asset_id); + if (!r) + { + fail_msg_writer() << "Failed to load asset_id from: " << args[0]; + return true; + } + + crypto::public_key new_owner = currency::null_pkey; + r = epee::string_tools::parse_tpod_from_hex_string(args[1], new_owner); + if (!r) + { + fail_msg_writer() << "Failed to load new owner public key from: " << args[1]; + return true; + } + + currency::asset_descriptor_base adb = AUTO_VAL_INIT(adb); + r = m_wallet->daemon_get_asset_info(asset_id, adb); + if (!r) + { + fail_msg_writer() << "Unknown asset: " << args[0]; + return true; + } + + currency::transaction result_tx = AUTO_VAL_INIT(result_tx); + m_wallet->transfer_asset_ownership(asset_id, new_owner, result_tx); + + success_msg_writer(true) << "Asset owner update tx sent: " << get_transaction_hash(result_tx) << " (unconfirmed) : " << ENDL + << "Asset ID: " << asset_id << ENDL + << "Title: " << adb.full_name << ENDL + << "Ticker: " << adb.ticker << ENDL + << "Emitted: " << print_fixed_decimal_point(adb.current_supply, adb.decimal_point) << ENDL + << "Max emission: " << print_fixed_decimal_point(adb.total_max_supply, adb.decimal_point) << ENDL + ; + + SIMPLE_WALLET_CATCH_TRY_ENTRY(); + return true; +} +//---------------------------------------------------------------------------------------------------- bool simple_wallet::add_custom_asset_id(const std::vector &args) { CONFIRM_WITH_PASSWORD(); diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 0b0843d0..70d46f32 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -96,7 +96,7 @@ namespace currency bool emit_asset(const std::vector &args); bool burn_asset(const std::vector &args); bool update_asset(const std::vector &args); - + bool transfer_asset_ownership(const std::vector& args); //---------------------------------------------------------------------------------------------------- bool generate_ionic_swap_proposal(const std::vector &args); bool get_ionic_swap_proposal_info(const std::vector &args); From d622078ef9a70248516523950db0b9fd207bfbcc Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Mon, 3 Jun 2024 20:57:53 +0400 Subject: [PATCH 11/53] added universal command that call rpc-api --- src/simplewallet/simplewallet.cpp | 43 +++++++++++++++++++++++++++++++ src/simplewallet/simplewallet.h | 1 + src/wallet/wallet_rpc_server.cpp | 2 +- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 381f5e24..dd72a2f4 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -348,6 +348,9 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("get_ionic_swap_proposal_info", boost::bind(&simple_wallet::get_ionic_swap_proposal_info, this, ph::_1), "get_ionic_swap_proposal_info - Extracts and display information from ionic_swap proposal raw data"); m_cmd_binder.set_handler("accept_ionic_swap_proposal", boost::bind(&simple_wallet::accept_ionic_swap_proposal, this, ph::_1), "accept_ionic_swap_proposal - Accept ionic_swap proposal and generates exchange transaction"); + m_cmd_binder.set_handler("call_rpc", boost::bind(&simple_wallet::call_rpc, this, ph::_1), "call_rpc - Invokes rpc request to the wallet"); + + } //---------------------------------------------------------------------------------------------------- simple_wallet::~simple_wallet() @@ -2087,6 +2090,46 @@ bool simple_wallet::deploy_new_asset(const std::vector &args) return true; } //---------------------------------------------------------------------------------------------------- +bool simple_wallet::call_rpc(const std::vector& args) +{ + CONFIRM_WITH_PASSWORD(); + SIMPLE_WALLET_BEGIN_TRY_ENTRY(); + if (!args.size() || args.size() > 2) + { + fail_msg_writer() << "invalid arguments count: " << args.size() << ", expected 1 or 2 (path to rpc request)"; + return true; + } + + std::string method = args[0]; + std::string method_body_request = "{}"; + + if (args.size() > 1) + { + bool r = epee::file_io_utils::load_file_to_string(args[1], method_body_request); + if (!r) + { + fail_msg_writer() << "invalid path: " << args[1] << ", failed to load body"; + return true; + } + } + + std::string req_full = "{\"id\": 0,\"jsonrpc\" : \"\", \"method\": \""; + req_full += method + "\",\"params\" : " + method_body_request + "}"; + + epee::net_utils::http::http_request_info query_info; + query_info.m_URI = "/json_rpc"; + query_info.m_body = req_full; + epee::net_utils::http::http_response_info response; + tools::wallet_rpc_server::connection_context conn_context(RPC_INTERNAL_UI_CONTEXT, 0, 0, false); + tools::wallet_rpc_server srv(m_wallet); + srv.handle_http_request(query_info, response, conn_context); + + success_msg_writer(true) << "Response code: " << response.m_response_code << ", body: " << ENDL << response.m_body; + + SIMPLE_WALLET_CATCH_TRY_ENTRY(); + return true; +} +//---------------------------------------------------------------------------------------------------- bool simple_wallet::emit_asset(const std::vector &args) { CONFIRM_WITH_PASSWORD(); diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 70d46f32..20dce45a 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -91,6 +91,7 @@ namespace currency bool tor_enable(const std::vector &args); bool tor_disable(const std::vector &args); bool deploy_new_asset(const std::vector &args); + bool call_rpc(const std::vector& args); bool add_custom_asset_id(const std::vector &args); bool remove_custom_asset_id(const std::vector &args); bool emit_asset(const std::vector &args); diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index e9f769f9..cc31eed5 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -1199,7 +1199,7 @@ namespace tools currency::assets_map_to_assets_list(res.global_whitelist, w.get_wallet()->get_global_whitelist()); currency::assets_map_to_assets_list(res.own_assets, w.get_wallet()->get_own_assets()); - const auto global_whitelist = w.get_wallet()->get_global_whitelist(); + //const auto global_whitelist = w.get_wallet()->get_global_whitelist(); return true; WALLET_RPC_CATCH_TRY_ENTRY(); From 47e10e7209745e7159b018db7d560ed021beaf0f Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 6 Jun 2024 21:24:14 +0200 Subject: [PATCH 12/53] added new api to update alias --- src/gui/qt-daemon/application/mainwindow.cpp | 2 +- src/wallet/wallet2.cpp | 19 +++++++++++++-- src/wallet/wallet2.h | 2 +- src/wallet/wallet_public_structs_defs.h | 23 ++++++++++++++++++ src/wallet/wallet_rpc_server.cpp | 25 ++++++++++++++++++++ src/wallet/wallet_rpc_server.h | 5 +++- src/wallet/wallets_manager.cpp | 4 ++-- src/wallet/wallets_manager.h | 2 +- tests/core_tests/hard_fork_2.cpp | 10 ++++---- tests/core_tests/wallet_tests.cpp | 2 +- 10 files changed, 80 insertions(+), 14 deletions(-) diff --git a/src/gui/qt-daemon/application/mainwindow.cpp b/src/gui/qt-daemon/application/mainwindow.cpp index 6cb817e0..d2f022ee 100644 --- a/src/gui/qt-daemon/application/mainwindow.cpp +++ b/src/gui/qt-daemon/application/mainwindow.cpp @@ -1294,7 +1294,7 @@ QString MainWindow::request_alias_update(const QString& param) // view::transfer_response tr = AUTO_VAL_INIT(tr); currency::transaction res_tx = AUTO_VAL_INIT(res_tx); - ar.error_code = m_backend.request_alias_update(tp.alias, tp.wallet_id, tp.fee, res_tx, tp.reward); + ar.error_code = m_backend.request_alias_update(tp.alias, tp.wallet_id, tp.fee, res_tx); if (ar.error_code != API_RETURN_CODE_OK) return MAKE_RESPONSE(ar); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index a48d5455..1907d8fa 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -5396,13 +5396,28 @@ bool wallet2::daemon_get_asset_info(const crypto::public_key& asset_id, currency return true; } //---------------------------------------------------------------------------------------------------- -void wallet2::request_alias_update(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward) +void wallet2::request_alias_update(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee) { + COMMAND_RPC_GET_ALIAS_DETAILS::request req; + req.alias = ai.m_alias; + COMMAND_RPC_GET_ALIAS_DETAILS::response rsp = AUTO_VAL_INIT(rsp); + bool r = m_core_proxy->call_COMMAND_RPC_GET_ALIAS_DETAILS(req, rsp); + CHECK_AND_ASSERT_THROW_MES(r, "Failed to call_COMMAND_RPC_GET_ALIAS_DETAILS"); + + CHECK_AND_ASSERT_THROW_MES(rsp.status == API_RETURN_CODE_OK, "call_COMMAND_RPC_GET_ALIAS_DETAILS response: " << rsp.status); + + + currency::account_public_address addr = AUTO_VAL_INIT(addr); + currency::get_account_address_from_str(addr, rsp.alias_details.address); + + CHECK_AND_ASSERT_THROW_MES(m_account.get_public_address().spend_public_key == addr.spend_public_key && + m_account.get_public_address().view_public_key == addr.view_public_key, "call_COMMAND_RPC_GET_ALIAS_DETAILS: ownership is not confirmed"); + if (!validate_alias_name(ai.m_alias)) { throw std::runtime_error(std::string("wrong alias characters: ") + ai.m_alias); } - bool r = currency::sign_extra_alias_entry(ai, m_account.get_keys().account_address.spend_public_key, m_account.get_keys().spend_secret_key); + r = currency::sign_extra_alias_entry(ai, m_account.get_keys().account_address.spend_public_key, m_account.get_keys().spend_secret_key); CHECK_AND_ASSERT_THROW_MES(r, "Failed to sign alias update"); WLT_LOG_L2("Generated update alias info: " << ENDL << "alias: " << ai.m_alias << ENDL diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 725c2c42..dd4718bd 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -416,7 +416,7 @@ namespace tools void cancel_offer_by_id(const crypto::hash& tx_id, uint64_t of_ind, uint64_t fee, currency::transaction& tx); void update_offer_by_id(const crypto::hash& tx_id, uint64_t of_ind, const bc_services::offer_details_ex& od, currency::transaction& res_tx); void request_alias_registration(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward = 0, const crypto::secret_key& authority_key = currency::null_skey); // if the given reward is 0, then the actual reward value will be requested via RPC - void request_alias_update(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward); + void request_alias_update(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee); bool check_available_sources(std::list& amounts); void deploy_new_asset(const currency::asset_descriptor_base& asset_info, const std::vector& destinations, currency::transaction& result_tx, crypto::public_key& new_asset_id); diff --git a/src/wallet/wallet_public_structs_defs.h b/src/wallet/wallet_public_structs_defs.h index 663fb080..b9a5ddb9 100644 --- a/src/wallet/wallet_public_structs_defs.h +++ b/src/wallet/wallet_public_structs_defs.h @@ -633,6 +633,29 @@ namespace wallet_public }; }; + struct COMMAND_RPC_UPDATE_ALIAS + { + DOC_COMMAND("Update an alias details/transwer alias ownership"); + + struct request + { + currency::alias_rpc_details al; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(al) DOC_DSCR("Alias details") DOC_END + END_KV_SERIALIZE_MAP() + }; + + struct response + { + crypto::hash tx_id; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE_POD_AS_HEX_STRING(tx_id) DOC_DSCR("If success - transactions that performs registration(alias becomes available after few confirmations)") DOC_EXMP("97d91442f8f3c22683585eaa60b53757d49bf046a96269cef45c1bc9ff7300cc") DOC_END + END_KV_SERIALIZE_MAP() + }; + }; + struct transfer_destination { diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index cc31eed5..9efaf197 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -968,6 +968,31 @@ namespace tools WALLET_RPC_CATCH_TRY_ENTRY(); } //------------------------------------------------------------------------------------------------------------------------------ + bool wallet_rpc_server::on_update_alias(const wallet_public::COMMAND_RPC_UPDATE_ALIAS::request& req, wallet_public::COMMAND_RPC_UPDATE_ALIAS::response& res, epee::json_rpc::error& er, connection_context& cntx) + { + WALLET_RPC_BEGIN_TRY_ENTRY(); + currency::extra_alias_entry ai = AUTO_VAL_INIT(ai); + if (!alias_rpc_details_to_alias_info(req.al, ai)) + { + er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS; + er.message = "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS"; + return false; + } + + if (!currency::validate_alias_name(ai.m_alias)) + { + er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS; + er.message = "WALLET_RPC_ERROR_CODE_WRONG_ADDRESS - Wrong alias name"; + return false; + } + + currency::transaction tx = AUTO_VAL_INIT(tx); + w.get_wallet()->request_alias_update(ai, tx, w.get_wallet()->get_default_fee()); + res.tx_id = get_transaction_hash(tx); + return true; + WALLET_RPC_CATCH_TRY_ENTRY(); + } + //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_contracts_send_proposal(const wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::request& req, wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx) { WALLET_RPC_BEGIN_TRY_ENTRY(); diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index 86a0039a..9ea31394 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -116,6 +116,8 @@ namespace tools MAP_JON_RPC_WE("get_seed_phrase_info", on_get_seed_phrase_info, wallet_public::COMMAND_RPC_GET_SEED_PHRASE_INFO) MAP_JON_RPC_WE("get_mining_history", on_get_mining_history, wallet_public::COMMAND_RPC_GET_MINING_HISTORY) MAP_JON_RPC_WE("register_alias", on_register_alias, wallet_public::COMMAND_RPC_REGISTER_ALIAS) + MAP_JON_RPC_WE("update_alias", on_update_alias, wallet_public::COMMAND_RPC_UPDATE_ALIAS) + //contracts API //MAP_JON_RPC_WE("contracts_send_proposal", on_contracts_send_proposal, wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL) //MAP_JON_RPC_WE("contracts_accept_proposal", on_contracts_accept_proposal, wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL) @@ -186,7 +188,8 @@ namespace tools bool on_search_for_transactions2(const wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::request& req, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::response& res, epee::json_rpc::error& er, connection_context& cntx); bool on_get_mining_history(const wallet_public::COMMAND_RPC_GET_MINING_HISTORY::request& req, wallet_public::COMMAND_RPC_GET_MINING_HISTORY::response& res, epee::json_rpc::error& er, connection_context& cntx); bool on_register_alias(const wallet_public::COMMAND_RPC_REGISTER_ALIAS::request& req, wallet_public::COMMAND_RPC_REGISTER_ALIAS::response& res, epee::json_rpc::error& er, connection_context& cntx); - + bool on_update_alias(const wallet_public::COMMAND_RPC_UPDATE_ALIAS::request& req, wallet_public::COMMAND_RPC_UPDATE_ALIAS::response& res, epee::json_rpc::error& er, connection_context& cntx); + bool on_contracts_send_proposal(const wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::request& req, wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx); bool on_contracts_accept_proposal(const wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL::request& req, wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx); diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index 02287be5..b039e86a 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -1459,7 +1459,7 @@ std::string wallets_manager::request_alias_registration(const currency::alias_rp return API_RETURN_CODE_ALREADY_EXISTS; } -std::string wallets_manager::request_alias_update(const currency::alias_rpc_details& al, uint64_t wallet_id, uint64_t fee, currency::transaction& res_tx, uint64_t reward) +std::string wallets_manager::request_alias_update(const currency::alias_rpc_details& al, uint64_t wallet_id, uint64_t fee, currency::transaction& res_tx) { currency::extra_alias_entry ai = AUTO_VAL_INIT(ai); if (!currency::alias_rpc_details_to_alias_info(al, ai)) @@ -1480,7 +1480,7 @@ std::string wallets_manager::request_alias_update(const currency::alias_rpc_deta std::string api_return_code_result = API_RETURN_CODE_FAIL; do_exception_safe_call( [&]() { - w->get()->request_alias_update(ai, res_tx, fee, reward); + w->get()->request_alias_update(ai, res_tx, fee); api_return_code_result = API_RETURN_CODE_OK; }, [&]() { return get_wallet_log_prefix(wallet_id) + "request_alias_update error: "; }, diff --git a/src/wallet/wallets_manager.h b/src/wallet/wallets_manager.h index 014ea3ef..01c62062 100644 --- a/src/wallet/wallets_manager.h +++ b/src/wallet/wallets_manager.h @@ -126,7 +126,7 @@ public: std::string get_alias_info_by_address(const std::string& addr, currency::alias_rpc_details& res_details); std::string get_alias_info_by_name(const std::string& name, currency::alias_rpc_details& res_details); std::string request_alias_registration(const currency::alias_rpc_details& al, uint64_t wallet_id, uint64_t fee, currency::transaction& res_tx, uint64_t reward); - std::string request_alias_update(const currency::alias_rpc_details& al, uint64_t wallet_id, uint64_t fee, currency::transaction& res_tx, uint64_t reward); + std::string request_alias_update(const currency::alias_rpc_details& al, uint64_t wallet_id, uint64_t fee, currency::transaction& res_tx); std::string get_alias_coast(const std::string& a, uint64_t& coast); std::string validate_address(const std::string& addr, std::string& payment_id); std::string resync_wallet(uint64_t wallet_id); diff --git a/tests/core_tests/hard_fork_2.cpp b/tests/core_tests/hard_fork_2.cpp index 173bb2b9..db02fd63 100644 --- a/tests/core_tests/hard_fork_2.cpp +++ b/tests/core_tests/hard_fork_2.cpp @@ -518,7 +518,7 @@ bool hard_fork_2_tx_extra_alias_entry_in_wallet::c1(currency::core& c, size_t ev r = false; try { - alice_wlt->request_alias_update(ai_alice_update, res_tx, TESTS_DEFAULT_FEE, 0); + alice_wlt->request_alias_update(ai_alice_update, res_tx, TESTS_DEFAULT_FEE); } catch (...) { @@ -540,7 +540,7 @@ bool hard_fork_2_tx_extra_alias_entry_in_wallet::c1(currency::core& c, size_t ev // update alias, change comment and address ai.m_text_comment = "Update to normal"; ai.m_address = m_accounts[MINER_ACC_IDX].get_public_address(); - alice_wlt->request_alias_update(ai, res_tx, TESTS_DEFAULT_FEE, 0); + alice_wlt->request_alias_update(ai, res_tx, TESTS_DEFAULT_FEE); CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count()); r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c); @@ -586,7 +586,7 @@ bool hard_fork_2_tx_extra_alias_entry_in_wallet::c1(currency::core& c, size_t ev // update alias once again, change comment and address to auditable // alias updated by miner, as he's the owner now - miner_wlt->request_alias_update(ai_alice_update, res_tx, TESTS_DEFAULT_FEE, 0); + miner_wlt->request_alias_update(ai_alice_update, res_tx, TESTS_DEFAULT_FEE); // after HF2: extra_alias_entry should be here, not extra_alias_entry_old r = have_type_in_variant_container(res_tx.extra); @@ -1221,7 +1221,7 @@ bool hard_fork_2_alias_update_using_old_tx::c1(currency::core& c, s // { transaction tx_upd = AUTO_VAL_INIT(tx_upd); - alice_wlt->request_alias_update(ai_upd, tx_upd, TESTS_DEFAULT_FEE, 0); + alice_wlt->request_alias_update(ai_upd, tx_upd, TESTS_DEFAULT_FEE); std::string tx_upd_hex = epee::string_tools::buff_to_hex_nodelimer(t_serializable_object_to_blob(tx_upd)); LOG_PRINT_L0("tx upd: " << ENDL << tx_upd_hex); } @@ -1334,7 +1334,7 @@ bool hard_fork_2_incorrect_alias_update::c1(currency::core& c, size r = false; try { - alice_wlt->request_alias_update(ai_upd, tx_upd, TESTS_DEFAULT_FEE, 0); + alice_wlt->request_alias_update(ai_upd, tx_upd, TESTS_DEFAULT_FEE); } catch (tools::error::tx_rejected&) { diff --git a/tests/core_tests/wallet_tests.cpp b/tests/core_tests/wallet_tests.cpp index bfadc1fb..ef10bf61 100644 --- a/tests/core_tests/wallet_tests.cpp +++ b/tests/core_tests/wallet_tests.cpp @@ -1868,7 +1868,7 @@ bool gen_wallet_alias_via_special_wallet_funcs::c1(currency::core& c, size_t ev_ ai.m_text_comment = "Update!"; ai.m_address = m_accounts[MINER_ACC_IDX].get_public_address(); - alice_wlt->request_alias_update(ai, res_tx, TESTS_DEFAULT_FEE, 0); + alice_wlt->request_alias_update(ai, res_tx, TESTS_DEFAULT_FEE); CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool"); r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c); From cdd435f0422215fa1b7f758573f3a2db7b40c2f0 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 14 Jun 2024 15:08:56 +0200 Subject: [PATCH 13/53] added update alias api + coretest --- src/rpc/core_rpc_server.h | 2 +- tests/core_tests/chaingen_main.cpp | 1 + tests/core_tests/wallet_rpc_tests.cpp | 192 +++++++++++++++++++++----- tests/core_tests/wallet_rpc_tests.h | 8 ++ 4 files changed, 167 insertions(+), 36 deletions(-) diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index ad4786f2..02e7b478 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -39,7 +39,7 @@ namespace currency void set_rpc_chain_handler(epee::net_utils::http::i_chain_handler* prpc_chain_handler) { m_prpc_chain_handler = prpc_chain_handler; } bool on_get_blocks_direct(const COMMAND_RPC_GET_BLOCKS_DIRECT::request& req, COMMAND_RPC_GET_BLOCKS_DIRECT::response& res, connection_context& cntx); - + void set_ignore_connectivity_status(bool ignore) { m_ignore_status = ignore;} bool on_get_height(const COMMAND_RPC_GET_HEIGHT::request& req, COMMAND_RPC_GET_HEIGHT::response& res, connection_context& cntx); bool on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res, connection_context& cntx); diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 8f69aebc..010c2230 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -1100,6 +1100,7 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(wallet_rpc_integrated_address); GENERATE_AND_PLAY(wallet_rpc_integrated_address_transfer); GENERATE_AND_PLAY(wallet_rpc_transfer); + GENERATE_AND_PLAY(wallet_rpc_alias_tests); GENERATE_AND_PLAY_HF(wallet_rpc_exchange_suite, "3,4"); GENERATE_AND_PLAY(wallet_chain_switch_with_spending_the_same_ki); GENERATE_AND_PLAY(wallet_sending_to_integrated_address); diff --git a/tests/core_tests/wallet_rpc_tests.cpp b/tests/core_tests/wallet_rpc_tests.cpp index e704855f..3fa4b2d7 100644 --- a/tests/core_tests/wallet_rpc_tests.cpp +++ b/tests/core_tests/wallet_rpc_tests.cpp @@ -6,12 +6,76 @@ #include "chaingen.h" #include "wallet_rpc_tests.h" #include "wallet_test_core_proxy.h" +#include "currency_core/currency_core.h" +#include "currency_core/bc_offers_service.h" +#include "rpc/core_rpc_server.h" +#include "currency_protocol/currency_protocol_handler.h" + + #include "../../src/wallet/wallet_rpc_server.h" #include "offers_helper.h" #include "random_helper.h" using namespace currency; +template +struct transport +{ + server_t& m_rpc_srv; + transport(server_t& rpc_srv) :m_rpc_srv(rpc_srv) + {} + epee::net_utils::http::http_response_info m_response; + + bool is_connected() { return true; } + template + bool connect(t_a ta, t_b tb, t_c tc) { return true; } + + template + bool invoke(const std::string uri, const std::string method_, const std::string& body, const epee::net_utils::http::http_response_info** ppresponse_info, const dummy_t& d) + { + epee::net_utils::http::http_request_info query_info; + query_info.m_URI = uri; + query_info.m_body = body; + tools::wallet_rpc_server::connection_context ctx; + bool r = m_rpc_srv.handle_http_request(query_info, m_response, ctx); + if (ppresponse_info) + *ppresponse_info = &m_response; + return r; + } +}; + + + +template +bool invoke_text_json_for_rpc(t_rpc_server& srv, const std::string& method_name, const request_t& req, response_t& resp) +{ + transport tr(srv); + + bool r = epee::net_utils::invoke_http_json_rpc("/json_rpc", method_name, req, resp, tr); + return r; +} + +template +bool invoke_text_json_for_wallet(std::shared_ptr wlt, const std::string& method_name, const request_t& req, response_t& resp) +{ + tools::wallet_rpc_server wlt_rpc_wrapper(wlt); + return invoke_text_json_for_rpc(wlt_rpc_wrapper, method_name, req, resp); +} + +template +bool invoke_text_json_for_core(currency::core& c, const std::string& method_name, const request_t& req, response_t& resp) +{ + currency::t_currency_protocol_handler m_cprotocol(c, nullptr); + nodetool::node_server > p2p(m_cprotocol); + bc_services::bc_offers_service of(nullptr); + + currency::core_rpc_server core_rpc_wrapper(c, p2p, of); + core_rpc_wrapper.set_ignore_connectivity_status(true); + return invoke_text_json_for_rpc(core_rpc_wrapper, method_name, req, resp); +} + + + wallet_rpc_integrated_address::wallet_rpc_integrated_address() { //REGISTER_CALLBACK_METHOD(wallet_rpc_integrated_address, c1); @@ -189,7 +253,6 @@ bool wallet_rpc_integrated_address_transfer::c1(currency::core& c, size_t ev_ind } //------------------------------------------------------------------------------ - wallet_rpc_transfer::wallet_rpc_transfer() { REGISTER_CALLBACK_METHOD(wallet_rpc_transfer, configure_core); @@ -300,7 +363,100 @@ bool wallet_rpc_transfer::c1(currency::core& c, size_t ev_index, const std::vect return true; } +//------------------------------------------------------------------------------ +wallet_rpc_alias_tests::wallet_rpc_alias_tests() +{ + REGISTER_CALLBACK_METHOD(wallet_rpc_alias_tests, configure_core); + REGISTER_CALLBACK_METHOD(wallet_rpc_alias_tests, 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 wallet_rpc_alias_tests::generate(std::vector& events) const +{ + m_accounts.resize(TOTAL_ACCS_COUNT); + account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); + account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); + account_base& bob_acc = m_accounts[BOB_ACC_IDX]; bob_acc.generate(); + + MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time()); + DO_CALLBACK(events, "configure_core"); // default callback will initialize core runtime config with m_hardforks + set_hard_fork_heights_to_generator(generator); + REWIND_BLOCKS_N(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 6); + + DO_CALLBACK(events, "c1"); + + return true; +} + +bool wallet_rpc_alias_tests::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); + std::shared_ptr alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX); + + miner_wlt->refresh(); + + { + tools::wallet_public::COMMAND_RPC_REGISTER_ALIAS::request req = AUTO_VAL_INIT(req); + tools::wallet_public::COMMAND_RPC_REGISTER_ALIAS::response rsp = AUTO_VAL_INIT(rsp); +#define ALIAS_FOR_TEST "monero" + + req.al.alias = ALIAS_FOR_TEST; + req.al.details.address = miner_wlt->get_account().get_public_address_str(); + req.al.details.comment = "XMR"; + r = invoke_text_json_for_wallet(miner_wlt, "register_alias", req, rsp); + CHECK_AND_ASSERT_MES(r, false, "failed to invoke_text_json_for_wallet"); + } + r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 3); + CHECK_AND_ASSERT_MES(r, false, "failed to mine_next_pow_blocks_in_playtime"); + + { + currency::COMMAND_RPC_GET_ALIAS_DETAILS::request req = AUTO_VAL_INIT(req); + currency::COMMAND_RPC_GET_ALIAS_DETAILS::response rsp = AUTO_VAL_INIT(rsp); + + req.alias = ALIAS_FOR_TEST; + r = invoke_text_json_for_core(c, "get_alias_details", req, rsp); + CHECK_AND_ASSERT_MES(r, false, "failed to invoke_text_json_for_wallet"); + CHECK_AND_ASSERT_MES(rsp.status == API_RETURN_CODE_OK, false, "failed to invoke_text_json_for_wallet"); + + CHECK_AND_ASSERT_MES(rsp.alias_details.address == miner_wlt->get_account().get_public_address_str(), false, "failed to invoke_text_json_for_wallet"); + } + + miner_wlt->refresh(); + + { + tools::wallet_public::COMMAND_RPC_UPDATE_ALIAS::request req = AUTO_VAL_INIT(req); + tools::wallet_public::COMMAND_RPC_UPDATE_ALIAS::response rsp = AUTO_VAL_INIT(rsp); + + req.al.alias = ALIAS_FOR_TEST; + req.al.details.address = alice_wlt->get_account().get_public_address_str(); + req.al.details.comment = "XMR of Alice"; + r = invoke_text_json_for_wallet(miner_wlt, "update_alias", req, rsp); + CHECK_AND_ASSERT_MES(r, false, "failed to invoke_text_json_for_wallet"); + } + + r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 3); + CHECK_AND_ASSERT_MES(r, false, "failed to mine_next_pow_blocks_in_playtime"); + + { + currency::COMMAND_RPC_GET_ALIAS_DETAILS::request req = AUTO_VAL_INIT(req); + currency::COMMAND_RPC_GET_ALIAS_DETAILS::response rsp = AUTO_VAL_INIT(rsp); + + req.alias = ALIAS_FOR_TEST; + r = invoke_text_json_for_core(c, "get_alias_details", req, rsp); + CHECK_AND_ASSERT_MES(r, false, "failed to invoke_text_json_for_wallet"); + CHECK_AND_ASSERT_MES(rsp.status == API_RETURN_CODE_OK, false, "failed to invoke_text_json_for_wallet"); + + CHECK_AND_ASSERT_MES(rsp.alias_details.address == alice_wlt->get_account().get_public_address_str(), false, "failed to invoke_text_json_for_wallet"); + } + + + return true; +} //------------------------------------------------------------------------------ wallet_rpc_exchange_suite::wallet_rpc_exchange_suite() @@ -322,40 +478,6 @@ bool wallet_rpc_exchange_suite::generate(std::vector& events) } -struct transport -{ - tools::wallet_rpc_server& m_rpc_srv; - transport(tools::wallet_rpc_server& rpc_srv):m_rpc_srv(rpc_srv) - {} - epee::net_utils::http::http_response_info m_response; - - bool is_connected() { return true; } - template - bool connect(t_a ta, t_b tb, t_c tc) { return true; } - - template - bool invoke(const std::string uri, const std::string method_, const std::string& body, const epee::net_utils::http::http_response_info** ppresponse_info, const dummy_t& d) - { - epee::net_utils::http::http_request_info query_info; - query_info.m_URI = uri; - query_info.m_body = body; - tools::wallet_rpc_server::connection_context ctx; - bool r = m_rpc_srv.handle_http_request(query_info, m_response, ctx); - if (ppresponse_info) - *ppresponse_info = &m_response; - return r; - } -}; - -template -bool invoke_text_json_for_rpc(tools::wallet_rpc_server& srv, const std::string& method_name, const request_t& req, response_t& resp) -{ - transport tr(srv); - - bool r = epee::net_utils::invoke_http_json_rpc("/json_rpc", method_name, req, resp, tr); - return r; -} - #include "wallet_rpc_tests_legacy_defs.h" diff --git a/tests/core_tests/wallet_rpc_tests.h b/tests/core_tests/wallet_rpc_tests.h index aa6e9b5e..0d939778 100644 --- a/tests/core_tests/wallet_rpc_tests.h +++ b/tests/core_tests/wallet_rpc_tests.h @@ -29,6 +29,14 @@ struct wallet_rpc_transfer : public wallet_test bool c1(currency::core& c, size_t ev_index, const std::vector& events); }; +struct wallet_rpc_alias_tests : public wallet_test +{ + wallet_rpc_alias_tests(); + bool generate(std::vector& events) const; + bool c1(currency::core& c, size_t ev_index, const std::vector& events); +}; + + /* Tests to make sure api for exchanges didn't change after HF4(Zarcanum) testing api: get_recent_txs_and_info, make_integrated_address, From 2f535f011ea0a44ae4b7aa06e51111bf0446f3b6 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 14 Jun 2024 23:20:43 +0200 Subject: [PATCH 14/53] fixed get_assets_list api --- src/currency_core/blockchain_storage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index c33161dd..419cdd1c 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -3888,7 +3888,7 @@ uint64_t blockchain_storage::get_assets(uint64_t offset, uint64_t count, std::li assets.push_back(asset_descriptor_with_id()); static_cast(assets.back()) = asset_descriptor_history.back().descriptor; assets.back().asset_id = asset_id; - if (i + count > offset) + if (assets.size() >= count) { return false; } From cb08646fc1fab5a482ef99a94e1c4a20fe7b719f Mon Sep 17 00:00:00 2001 From: zano build machine Date: Mon, 17 Jun 2024 01:42:12 +0300 Subject: [PATCH 15/53] === build number: 317 -> 318 === --- src/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h.in b/src/version.h.in index 6819f5d7..08cefedc 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -8,6 +8,6 @@ #define PROJECT_REVISION "0" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 317 +#define PROJECT_VERSION_BUILD_NO 318 #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 "]" From af49225221384bda4082520f8d4dd6051f9466c8 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Mon, 17 Jun 2024 22:12:49 +0200 Subject: [PATCH 16/53] small tweak for bridge serialization --- .../epee/include/serialization/keyvalue_helpers.h | 5 +++++ src/gui/qt-daemon/application/mainwindow.cpp | 15 +++++++++------ src/gui/qt-daemon/application/mainwindow.h | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/contrib/epee/include/serialization/keyvalue_helpers.h b/contrib/epee/include/serialization/keyvalue_helpers.h index 7dc812ad..9b5f0dcf 100644 --- a/contrib/epee/include/serialization/keyvalue_helpers.h +++ b/contrib/epee/include/serialization/keyvalue_helpers.h @@ -121,8 +121,13 @@ namespace epee boost::split(pod_items, a, boost::is_any_of(", ][\"")); t_pod_container_type res; + if (!a.size()) + return res; for (const auto& item : pod_items) { + if(!item.size()) + continue; + res.resize(res.size() + 1); typename t_pod_container_type::value_type& pod_val = res.back(); diff --git a/src/gui/qt-daemon/application/mainwindow.cpp b/src/gui/qt-daemon/application/mainwindow.cpp index d2f022ee..dc512fa0 100644 --- a/src/gui/qt-daemon/application/mainwindow.cpp +++ b/src/gui/qt-daemon/application/mainwindow.cpp @@ -978,18 +978,21 @@ QString MainWindow::start_backend(const QString& params) QString MainWindow::sync_call(const QString& func_name, const QString& params) { - if (func_name == "transfer") - { - return this->transfer(params); - } - else if (func_name == "test_call") + if (func_name == "test_call") { return params; } + std::string fuc_name_std = func_name.toStdString(); + QString response_str; + bool r = QMetaObject::invokeMethod(this, fuc_name_std.c_str(), Qt::DirectConnection, Q_RETURN_ARG(QString, response_str), Q_ARG(QString, params)); + //bool r = this->invokeMethod(fuc_name_std.c_str(), Q_RETURN_ARG(QString, response_str), Q_ARG(QString, params)); + if (r) + return response_str; else { - return QString(QString() + "{ \"status\": \"Method '" + func_name + "' not found\"}"); + return QString(QString() + "{ \"status\": \"Method '" + func_name + "' not found\"}"); } + } QString MainWindow::async_call(const QString& func_name, const QString& params) diff --git a/src/gui/qt-daemon/application/mainwindow.h b/src/gui/qt-daemon/application/mainwindow.h index 074fb9f5..da9f2ee5 100644 --- a/src/gui/qt-daemon/application/mainwindow.h +++ b/src/gui/qt-daemon/application/mainwindow.h @@ -110,7 +110,7 @@ public: QString get_version(const QString& param); QString get_os_version(const QString& param); QString get_network_type(const QString& param); - QString transfer(const QString& json_transfer_object); + QString transfer(const QString& param); QString have_secure_app_data(const QString& param); QString drop_secure_app_data(const QString& param); QString get_secure_app_data(const QString& param); From 5f62c76a2f8938f8b0a2be3c22f91b62e2ca6ff9 Mon Sep 17 00:00:00 2001 From: zano build machine Date: Wed, 19 Jun 2024 00:55:44 +0300 Subject: [PATCH 17/53] === build number: 318 -> 319 === --- src/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h.in b/src/version.h.in index 08cefedc..16f93fa2 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -8,6 +8,6 @@ #define PROJECT_REVISION "0" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 318 +#define PROJECT_VERSION_BUILD_NO 319 #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 "]" From c01e9a58629bdd1c264c064d4fa0b74583b4c115 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 19 Jun 2024 14:45:21 +0200 Subject: [PATCH 18/53] added async call for 2-arguments slots --- src/gui/qt-daemon/application/mainwindow.cpp | 34 ++++++++++++++++++++ src/gui/qt-daemon/application/mainwindow.h | 3 ++ 2 files changed, 37 insertions(+) diff --git a/src/gui/qt-daemon/application/mainwindow.cpp b/src/gui/qt-daemon/application/mainwindow.cpp index dc512fa0..40758a4a 100644 --- a/src/gui/qt-daemon/application/mainwindow.cpp +++ b/src/gui/qt-daemon/application/mainwindow.cpp @@ -995,6 +995,21 @@ QString MainWindow::sync_call(const QString& func_name, const QString& params) } +QString MainWindow::sync_call_2a(const QString& func_name, const QString& params1, const QString& params2) +{ + std::string fuc_name_std = func_name.toStdString(); + QString response_str; + bool r = QMetaObject::invokeMethod(this, fuc_name_std.c_str(), Qt::DirectConnection, Q_RETURN_ARG(QString, response_str), Q_ARG(QString, params1), Q_ARG(QString, params2)); + //bool r = this->invokeMethod(fuc_name_std.c_str(), Q_RETURN_ARG(QString, response_str), Q_ARG(QString, params)); + if (r) + return response_str; + else + { + return QString(QString() + "{ \"status\": \"Method '" + func_name + "' not found\"}"); + } + +} + QString MainWindow::async_call(const QString& func_name, const QString& params) { @@ -1013,6 +1028,25 @@ QString MainWindow::async_call(const QString& func_name, const QString& params) return QString::fromStdString(std::string("{ \"job_id\": ") + std::to_string(job_id) + "}"); } +QString MainWindow::async_call_2a(const QString& func_name, const QString& params1, const QString& params2) +{ + + uint64_t job_id = m_ui_dispatch_id_counter++; + QString method_name = func_name; + QString argements1 = params1; + QString argements2 = params2; + + + auto async_callback = [this, method_name, argements1, argements2, job_id]() + { + QString res_str = this->sync_call_2a(method_name, argements1, argements2); + this->dispatch_async_call_result(std::to_string(job_id).c_str(), res_str); //general function + }; + + m_threads_pool.add_job(async_callback); + LOG_PRINT_L2("[UI_ASYNC_CALL]: started " << method_name.toStdString() << ", job id: " << job_id); + return QString::fromStdString(std::string("{ \"job_id\": ") + std::to_string(job_id) + "}"); +} bool MainWindow::update_wallet_status(const view::wallet_status_info& wsi) { diff --git a/src/gui/qt-daemon/application/mainwindow.h b/src/gui/qt-daemon/application/mainwindow.h index da9f2ee5..0f575b6b 100644 --- a/src/gui/qt-daemon/application/mainwindow.h +++ b/src/gui/qt-daemon/application/mainwindow.h @@ -193,6 +193,9 @@ public: QString async_call(const QString& func_name, const QString& params); QString sync_call(const QString& func_name, const QString& params); + + QString async_call_2a(const QString& func_name, const QString& params1, const QString& params2); + QString sync_call_2a(const QString& func_name, const QString& params1, const QString& params2); //for test purposes only QString request_dummy(const QString& param); From 6408ea007ff9df2e0473e3c550816e8470224c8b Mon Sep 17 00:00:00 2001 From: sowle Date: Sat, 22 Jun 2024 19:55:14 +0200 Subject: [PATCH 19/53] ui update --- src/gui/qt-daemon/layout | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/qt-daemon/layout b/src/gui/qt-daemon/layout index 9be6a53f..fb814ffb 160000 --- a/src/gui/qt-daemon/layout +++ b/src/gui/qt-daemon/layout @@ -1 +1 @@ -Subproject commit 9be6a53f757a17403ea5798d08b577d450eb620a +Subproject commit fb814ffb346375996dc2586d7e814f28bfe15ddd From 3882d024cb0591b9c7dbdaca768a7b19e52aad57 Mon Sep 17 00:00:00 2001 From: sowle Date: Sat, 22 Jun 2024 20:25:04 +0200 Subject: [PATCH 20/53] simplewallet: display own assets with correct decimal point, get_asset_info() knows own assets, + minor fixes --- src/simplewallet/simplewallet.cpp | 31 +++++++++++-------- src/simplewallet/simplewallet.h | 2 +- src/wallet/wallet2.cpp | 49 +++++++++++++++++-------------- src/wallet/wallet2.h | 5 +++- 4 files changed, 51 insertions(+), 36 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index dd72a2f4..fb1c3a61 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -816,38 +816,45 @@ void simple_wallet::on_new_block(uint64_t height, const currency::block& block) //---------------------------------------------------------------------------------------------------- std::string print_money_trailing_zeros_replaced_with_spaces(uint64_t amount, size_t decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT) { - std::string s = print_money(amount); + std::string s = print_money(amount, decimal_point); size_t p = s.find_last_not_of('0'); if (p != std::string::npos) { if (s[p] == '.') ++p; size_t l = s.length() - p - 1; - return s.replace(p + 1, l, l, ' '); + s.replace(p + 1, l, l, ' '); + if (decimal_point < CURRENCY_DISPLAY_DECIMAL_POINT) + s += std::string(CURRENCY_DISPLAY_DECIMAL_POINT - decimal_point, ' '); } return s; } //---------------------------------------------------------------------------------------------------- -std::string simple_wallet::get_tocken_info_string(const crypto::public_key& asset_id, uint64_t& decimal_points) +std::string simple_wallet::get_token_info_string(const crypto::public_key& asset_id, uint64_t& decimal_points) { std::string token_info = "ZANO"; decimal_points = CURRENCY_DISPLAY_DECIMAL_POINT; if (asset_id != currency::native_coin_asset_id) { currency::asset_descriptor_base adb = AUTO_VAL_INIT(adb); - bool whitelisted = false; - if (!m_wallet->get_asset_id_info(asset_id, adb, whitelisted)) + uint32_t asset_info_flags{}; + if (!m_wallet->get_asset_info(asset_id, adb, asset_info_flags)) { token_info = "!UNKNOWN!"; } - else { + else + { decimal_points = adb.decimal_point; token_info = adb.ticker; - if (whitelisted) + if (asset_info_flags & tools::wallet2::aif_whitelisted) { token_info += "[*]"; } + else if (asset_info_flags & tools::wallet2::aif_own) + { + token_info += "[$]"; + } else { token_info += std::string("[") + epee::string_tools::pod_to_hex(asset_id) + "]"; @@ -864,7 +871,7 @@ void simple_wallet::on_transfer2(const tools::wallet_public::wallet_transfer_inf { epee::log_space::console_colors color = !wti.has_outgoing_entries() ? epee::log_space::console_color_green : epee::log_space::console_color_magenta; uint64_t decimal_points = CURRENCY_DISPLAY_DECIMAL_POINT; - std::string token_info = get_tocken_info_string(wti.subtransfers[0].asset_id, decimal_points); + std::string token_info = get_token_info_string(wti.subtransfers[0].asset_id, decimal_points); message_writer(color, false) << "height " << wti.height << ", tx " << wti.tx_hash << @@ -879,10 +886,10 @@ void simple_wallet::on_transfer2(const tools::wallet_public::wallet_transfer_inf { epee::log_space::console_colors color = st.is_income ? epee::log_space::console_color_green : epee::log_space::console_color_magenta; uint64_t decimal_points = CURRENCY_DISPLAY_DECIMAL_POINT; - std::string token_info = get_tocken_info_string(st.asset_id, decimal_points); + std::string token_info = get_token_info_string(st.asset_id, decimal_points); - message_writer(epee::log_space::console_color_cyan, false) << " " - << std::right << std::setw(18) << print_money_trailing_zeros_replaced_with_spaces(st.amount, decimal_points) << (st.is_income ? " received," : " spent") << " " << token_info; + message_writer(epee::log_space::console_color_cyan, false) << " " + << std::right << std::setw(24) << print_money_trailing_zeros_replaced_with_spaces(st.amount, decimal_points) << std::left << (st.is_income ? " received," : " spent") << " " << token_info; } } @@ -1059,7 +1066,7 @@ bool simple_wallet::print_wti(const tools::wallet_public::wallet_transfer_info& { epee::log_space::console_colors cl = st.is_income ? epee::log_space::console_color_green: epee::log_space::console_color_magenta; uint64_t decimal_points = CURRENCY_DISPLAY_DECIMAL_POINT; - std::string token_info = get_tocken_info_string(st.asset_id, decimal_points); + std::string token_info = get_token_info_string(st.asset_id, decimal_points); success_msg_writer(cl) << (st.is_income ? "Received " : "Sent ") diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 20dce45a..5f260433 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -110,7 +110,7 @@ namespace currency uint64_t get_daemon_blockchain_height(std::string& err); bool try_connect_to_daemon(); - std::string get_tocken_info_string(const crypto::public_key& asset_id, uint64_t& decimal_point); + std::string get_token_info_string(const crypto::public_key& asset_id, uint64_t& decimal_point); bool print_wti(const tools::wallet_public::wallet_transfer_info& wti); bool check_password_for_operation(); crypto::hash get_hash_from_pass_and_salt(const std::string& pass, uint64_t salt); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 1907d8fa..5effc4f1 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3813,37 +3813,42 @@ bool wallet2::balance(std::list& balances, u return true; } //---------------------------------------------------------------------------------------------------- -bool wallet2::get_asset_id_info(const crypto::public_key& asset_id, currency::asset_descriptor_base& asset_info, bool& whitelist_) const +bool wallet2::get_asset_info(const crypto::public_key& asset_id, currency::asset_descriptor_base& asset_info, uint32_t& asset_flags) const { + asset_flags = aif_none; if (asset_id == currency::native_coin_asset_id) { asset_info = currency::get_native_coin_asset_descriptor(); - whitelist_ = true; + asset_flags |= aif_whitelisted; return true; } - //check if asset is whitelisted or customly added - whitelist_ = false; + + // whitelisted? auto it_white = m_whitelisted_assets.find(asset_id); - if (it_white == m_whitelisted_assets.end()) - { - //check if it custom asset - auto it_cust = m_custom_assets.find(asset_id); - if (it_cust == m_custom_assets.end()) - { - return false; - } - else - { - asset_info = it_cust->second; - } - } - else + if (it_white != m_whitelisted_assets.end()) { asset_info = it_white->second; - whitelist_ = true; + asset_flags |= aif_whitelisted; + return true; } - return true; + // custom asset? + auto it_cust = m_custom_assets.find(asset_id); + if (it_cust != m_custom_assets.end()) + { + asset_info = it_cust->second; + return true; + } + + auto it_own = m_own_asset_descriptors.find(asset_id); + if (it_own != m_own_asset_descriptors.end()) + { + asset_info = it_own->second; + asset_flags |= aif_own; + return true; + } + + return false; } //---------------------------------------------------------------------------------------------------- @@ -3965,8 +3970,8 @@ std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool inclu bool native_coin = td.is_native_coin(); asset_descriptor_base adb{}; - bool whitelisted = false; - if (get_asset_id_info(td.get_asset_id(), adb, whitelisted) == show_only_unknown) + uint32_t asset_info_flags{}; + if (get_asset_info(td.get_asset_id(), adb, asset_info_flags) == show_only_unknown) { if (!show_only_unknown) ++unknown_assets_outs_count; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index dd4718bd..448af662 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -441,7 +441,10 @@ namespace tools uint64_t balance(uint64_t& unloked) const; uint64_t unlocked_balance() const; - bool get_asset_id_info(const crypto::public_key& asset_id, currency::asset_descriptor_base& asset_info, bool& whitelist_) const; + + enum asset_info_flags_t : uint32_t { aif_none = 0, aif_whitelisted = 1 << 0, aif_own = 1 << 1 }; + bool get_asset_info(const crypto::public_key& asset_id, currency::asset_descriptor_base& asset_info, uint32_t& asset_flags) const; + void transfer(uint64_t amount, const currency::account_public_address& acc, const crypto::public_key& asset_id = currency::native_coin_asset_id); void transfer(uint64_t amount, size_t fake_outs_count, const currency::account_public_address& acc, uint64_t fee = TX_DEFAULT_FEE, const crypto::public_key& asset_id = currency::native_coin_asset_id); void transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx, const crypto::public_key& asset_id = currency::native_coin_asset_id); From 63c2a299a50e836b407505ecc90b06a4dccbe3a1 Mon Sep 17 00:00:00 2001 From: zano build machine Date: Sat, 22 Jun 2024 21:37:45 +0300 Subject: [PATCH 21/53] === build number: 319 -> 320 === --- src/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h.in b/src/version.h.in index 16f93fa2..6858efe8 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -8,6 +8,6 @@ #define PROJECT_REVISION "0" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 319 +#define PROJECT_VERSION_BUILD_NO 320 #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 "]" From c21785add4a618f46f23fa690f6a9867472e977f Mon Sep 17 00:00:00 2001 From: sowle Date: Mon, 24 Jun 2024 12:16:42 +0200 Subject: [PATCH 22/53] fix for #440 --- .../currency_format_utils_transactions.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/currency_core/currency_format_utils_transactions.h b/src/currency_core/currency_format_utils_transactions.h index aeaa551a..f608b4eb 100644 --- a/src/currency_core/currency_format_utils_transactions.h +++ b/src/currency_core/currency_format_utils_transactions.h @@ -286,15 +286,15 @@ namespace currency // consider redesign, some data may possibly be excluded from kv serialization -- sowle BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(asset_ids) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(blinded_asset_ids) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(amount_commitments) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(asset_id_blinding_masks) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(amounts) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(amount_blinding_masks) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(pseudo_outs_blinded_asset_ids) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(pseudo_outs_plus_real_out_blinding_masks) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(real_zc_ins_asset_ids) + KV_SERIALIZE_CONTAINER_POD_AS_HEX(asset_ids) + KV_SERIALIZE_CONTAINER_POD_AS_HEX(blinded_asset_ids) + KV_SERIALIZE_CONTAINER_POD_AS_HEX(amount_commitments) + KV_SERIALIZE_CONTAINER_POD_AS_HEX(asset_id_blinding_masks) + KV_SERIALIZE_CONTAINER_POD_AS_HEX(amounts) + KV_SERIALIZE_CONTAINER_POD_AS_HEX(amount_blinding_masks) + KV_SERIALIZE_CONTAINER_POD_AS_HEX(pseudo_outs_blinded_asset_ids) + KV_SERIALIZE_CONTAINER_POD_AS_HEX(pseudo_outs_plus_real_out_blinding_masks) + KV_SERIALIZE_CONTAINER_POD_AS_HEX(real_zc_ins_asset_ids) KV_SERIALIZE(zc_input_amounts) KV_SERIALIZE_POD_AS_HEX_STRING(pseudo_out_amount_commitments_sum) KV_SERIALIZE_POD_AS_HEX_STRING(pseudo_out_amount_blinding_masks_sum) From 226c3653ac12dc6391c37af61fc626fced1e92c8 Mon Sep 17 00:00:00 2001 From: sowle Date: Mon, 24 Jun 2024 23:28:47 +0200 Subject: [PATCH 23/53] minor improvements: CHECK_AND_ASSERT_EQ(), stream support for std::type_info --- contrib/epee/include/misc_log_ex.h | 21 ++++++++++++++++----- src/currency_core/currency_format_utils.cpp | 5 +++++ src/currency_core/currency_format_utils.h | 1 + 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h index 318237c9..376af660 100644 --- a/contrib/epee/include/misc_log_ex.h +++ b/contrib/epee/include/misc_log_ex.h @@ -244,11 +244,6 @@ DISABLE_VS_WARNINGS(4100) #define CHECK_AND_ASSERT_MES_CUSTOM(expr, fail_ret_val, custom_code, message) do{if(!(expr)) {LOG_ERROR(message); custom_code; return fail_ret_val;};}while(0) #endif -/*#ifndef CHECK_AND_ASSERT_MES_AND_THROW -#define CHECK_AND_ASSERT_MES_AND_THROW(expr, message) do{if(!(expr)) {LOG_ERROR(message); throw std::runtime_error(message);};}while(0) -#endif -*/ - #ifndef CHECK_AND_NO_ASSERT_MES #define CHECK_AND_NO_ASSERT_MES(expr, fail_ret_val, message) do{if(!(expr)) {LOG_PRINT_MAGENTA(message, LOG_LEVEL_0); /*LOCAL_ASSERT(expr);*/ return fail_ret_val;};}while(0) #endif @@ -265,6 +260,22 @@ DISABLE_VS_WARNINGS(4100) #define CHECK_AND_ASSERT_MES2(expr, message) do{if(!(expr)) {LOG_ERROR(message); };}while(0) #endif +#ifndef CHECK_AND_ASSERT_EQ +#define CHECK_AND_ASSERT_EQ(A, B) CHECK_AND_ASSERT_MES((A) == (B), false, STR(A) " != " STR(B) " because " << A << " != " << B) +#endif + +#ifndef CHECK_AND_ASSERT_NEQ +#define CHECK_AND_ASSERT_NEQ(A, B) CHECK_AND_ASSERT_MES((A) != (B), false, STR(A) " == " STR(B) " because " << A << " == " << B) +#endif + +#ifndef CHECK_AND_ASSERT_LESS +#define CHECK_AND_ASSERT_LESS(A, B) CHECK_AND_ASSERT_MES((A) < (B), false, STR(A) " >= " STR(B) " because " << A << " >= " << B) +#endif + +#ifndef CHECK_AND_ASSERT_GREATER +#define CHECK_AND_ASSERT_GREATER(A, B) CHECK_AND_ASSERT_MES((A) > (B), false, STR(A) " <= " STR(B) " because " << A << " <= " << B) +#endif + namespace epee { namespace debug diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 556f371e..2c8e5c2a 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -4463,6 +4463,11 @@ namespace currency return o << "<" << r.n << ":" << r.tx_id << ">"; } //-------------------------------------------------------------------------------- + std::ostream& operator <<(std::ostream& o, const std::type_info& ti) + { + return o << ti.name(); + } + //-------------------------------------------------------------------------------- #ifndef MOBILE_WALLET_BUILD const std::locale& utf8_get_conversion_locale() { diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index fd33a6b8..5c4ea929 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -945,6 +945,7 @@ namespace currency //--------------------------------------------------------------- //--------------------------------------------------------------- std::ostream& operator <<(std::ostream& o, const ref_by_id& r); + std::ostream& operator <<(std::ostream& o, const std::type_info& ti); //--------------------------------------------------------------- #ifndef MOBILE_WALLET_BUILD std::string utf8_to_upper(const std::string& s); From 5e8cfb9ee36cf7606190daafbe2bd2bff2293c80 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 25 Jun 2024 14:41:36 +0200 Subject: [PATCH 24/53] coretests: hard_fork_2_incorrect_alias_update fixed due to change in logic of wallet2::request_alias_update() --- tests/core_tests/hard_fork_2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core_tests/hard_fork_2.cpp b/tests/core_tests/hard_fork_2.cpp index db02fd63..7ce86a5b 100644 --- a/tests/core_tests/hard_fork_2.cpp +++ b/tests/core_tests/hard_fork_2.cpp @@ -1336,7 +1336,7 @@ bool hard_fork_2_incorrect_alias_update::c1(currency::core& c, size { alice_wlt->request_alias_update(ai_upd, tx_upd, TESTS_DEFAULT_FEE); } - catch (tools::error::tx_rejected&) + catch(std::runtime_error&) { // this should cause an exception with certain type r = true; From 5ab468be42e2cc08fb1adcd6ff011309744acf2c Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 25 Jun 2024 15:46:53 +0200 Subject: [PATCH 25/53] validate_tx_details_against_tx_generation_context implemented --- .../currency_format_utils_transactions.cpp | 112 ++++++++++++++++-- .../currency_format_utils_transactions.h | 3 +- src/wallet/wallet2.cpp | 4 +- 3 files changed, 109 insertions(+), 10 deletions(-) diff --git a/src/currency_core/currency_format_utils_transactions.cpp b/src/currency_core/currency_format_utils_transactions.cpp index 291010a6..6c4a5a2e 100644 --- a/src/currency_core/currency_format_utils_transactions.cpp +++ b/src/currency_core/currency_format_utils_transactions.cpp @@ -398,14 +398,112 @@ namespace currency CATCH_ENTRY2(std::vector{}); } //--------------------------------------------------------------- - bool validate_tx_output_details_againt_tx_generation_context(const transaction& tx, const tx_generation_context& gen_context) + bool validate_tx_details_against_tx_generation_context(const transaction& tx, const tx_generation_context& tgc) { - //TODO: Implement this function before mainnet -#ifdef TESTNET + CHECK_AND_ASSERT_MES(tx.version >= TRANSACTION_VERSION_POST_HF4, false, "validate_tx_details_against_tx_generation_context should never be called for pre-HF4 txs"); + + // + // outputs + // (all outputs are ZC outputs, because we require tx.version to be post-HF4) + size_t tx_outs_count = tx.vout.size(); + CHECK_AND_ASSERT_EQ(tgc.asset_ids.size(), tx_outs_count); + CHECK_AND_ASSERT_EQ(tgc.blinded_asset_ids.size(), tx_outs_count); + CHECK_AND_ASSERT_EQ(tgc.amount_commitments.size(), tx_outs_count); + CHECK_AND_ASSERT_EQ(tgc.asset_id_blinding_masks.size(), tx_outs_count); + CHECK_AND_ASSERT_EQ(tgc.amounts.size(), tx_outs_count); + CHECK_AND_ASSERT_EQ(tgc.amount_blinding_masks.size(), tx_outs_count); + + crypto::point_t amount_commitments_sum = crypto::c_point_0; + crypto::scalar_t amount_blinding_masks_sum{}; + crypto::scalar_t asset_id_blinding_mask_x_amount_sum{}; + for(size_t i = 0; i < tx_outs_count; ++i) + { + crypto::point_t calculated_T = tgc.asset_ids[i] + tgc.asset_id_blinding_masks[i] * crypto::c_point_X; + CHECK_AND_ASSERT_MES(calculated_T.is_in_main_subgroup(), false, "calculated_T isn't in the main subgroup"); + CHECK_AND_ASSERT_EQ(tgc.blinded_asset_ids[i], calculated_T); + + crypto::point_t calculated_A = tgc.amounts[i] * calculated_T + tgc.amount_blinding_masks[i] * crypto::c_point_G; + CHECK_AND_ASSERT_MES(calculated_A.is_in_main_subgroup(), false, "calculated_A isn't in the main subgroup"); + CHECK_AND_ASSERT_EQ(tgc.amount_commitments[i], calculated_A); + + const tx_out_zarcanum& tx_out_zc = boost::get(tx.vout[i]); + crypto::point_t tx_T = crypto::point_t(tx_out_zc.blinded_asset_id).modify_mul8(); + CHECK_AND_ASSERT_EQ(tgc.blinded_asset_ids[i], tx_T); + crypto::point_t tx_A = crypto::point_t(tx_out_zc.amount_commitment).modify_mul8(); + CHECK_AND_ASSERT_EQ(tgc.amount_commitments[i], tx_A); + amount_commitments_sum += calculated_A; + amount_blinding_masks_sum += tgc.amount_blinding_masks[i]; + asset_id_blinding_mask_x_amount_sum += tgc.asset_id_blinding_masks[i] * tgc.amounts[i]; + } + CHECK_AND_ASSERT_EQ(tgc.amount_commitments_sum, amount_commitments_sum); + CHECK_AND_ASSERT_EQ(tgc.amount_blinding_masks_sum, amount_blinding_masks_sum); + CHECK_AND_ASSERT_EQ(tgc.asset_id_blinding_mask_x_amount_sum, asset_id_blinding_mask_x_amount_sum); + + // + // inputs + // + + size_t tx_inputs_count = tx.vin.size(); + size_t tx_zc_inputs_count = count_type_in_variant_container(tx.vin); + size_t tx_bare_inputs_count = count_type_in_variant_container(tx.vin); + CHECK_AND_ASSERT_EQ(tx_inputs_count, tx_zc_inputs_count + tx_bare_inputs_count); + CHECK_AND_ASSERT_EQ(tx.signatures.size(), tx.vin.size()); // can do this because we shouldn't face additional signature so far + + CHECK_AND_ASSERT_EQ(tgc.pseudo_outs_blinded_asset_ids.size(), tx_zc_inputs_count); + CHECK_AND_ASSERT_EQ(tgc.pseudo_outs_plus_real_out_blinding_masks.size(), tx_zc_inputs_count); + CHECK_AND_ASSERT_EQ(tgc.real_zc_ins_asset_ids.size(), tx_zc_inputs_count); + CHECK_AND_ASSERT_EQ(tgc.zc_input_amounts.size(), tx_zc_inputs_count); + + crypto::point_t pseudo_out_amount_commitments_sum = crypto::c_point_0; + + for(size_t input_index = 0, zc_input_index = 0; input_index < tx.vin.size(); ++input_index) + { + const txin_v& in_v = tx.vin[input_index]; + if (in_v.type() == typeid(txin_zc_input)) + { + CHECK_AND_ASSERT_EQ(tx.signatures[input_index].type(), typeid(ZC_sig)); + const ZC_sig& sig = boost::get(tx.signatures[input_index]); + + crypto::point_t sig_pseudo_out_amount_commitment = crypto::point_t(sig.pseudo_out_amount_commitment).modify_mul8(); + crypto::point_t sig_pseudo_out_blinded_asset_id = crypto::point_t(sig.pseudo_out_blinded_asset_id).modify_mul8(); + + crypto::point_t pseudo_out_blinded_asset_id_calculated = tgc.real_zc_ins_asset_ids[zc_input_index] + tgc.pseudo_outs_plus_real_out_blinding_masks[zc_input_index] * crypto::c_point_X; // T^P = H_i + r_pi*X + r'_i*X + CHECK_AND_ASSERT_EQ(sig_pseudo_out_blinded_asset_id, pseudo_out_blinded_asset_id_calculated); + CHECK_AND_ASSERT_EQ(tgc.pseudo_outs_blinded_asset_ids[zc_input_index], pseudo_out_blinded_asset_id_calculated); + CHECK_AND_ASSERT_MES(pseudo_out_blinded_asset_id_calculated.is_in_main_subgroup(), false, "pseudo_out_blinded_asset_id_calculated isn't in the main subgroup"); + // cannot be verified: + // tgc.zc_input_amounts[zc_input_index]; // ZC only input amounts + + pseudo_out_amount_commitments_sum += sig_pseudo_out_amount_commitment; + ++zc_input_index; + } + else if (in_v.type() == typeid(txin_to_key)) + { + // do nothing + } + else + { + // should never get here + CHECK_AND_ASSERT_MES(false, false, "internal error, unexpected type: " << in_v.type().name()); + } + } + + // tx secret and public keys + CHECK_AND_ASSERT_MES(tgc.tx_pub_key_p.is_in_main_subgroup(), false, "tgc.tx_pub_key_p isn't in the main subgroup"); + CHECK_AND_ASSERT_EQ(tgc.tx_pub_key_p.to_public_key(), tgc.tx_key.pub); + CHECK_AND_ASSERT_EQ(crypto::scalar_t(tgc.tx_key.sec) * crypto::c_point_G, tgc.tx_pub_key_p); + + // no ongoing asset operation + CHECK_AND_ASSERT_EQ(tgc.ao_asset_id, currency::null_pkey); + CHECK_AND_ASSERT_EQ(tgc.ao_asset_id_pt, crypto::c_point_0); + CHECK_AND_ASSERT_EQ(tgc.ao_amount_commitment, crypto::c_point_0); + CHECK_AND_ASSERT_EQ(tgc.ao_amount_blinding_mask, crypto::c_scalar_0); + + // cannot be verified: + // tgc.pseudo_out_amount_blinding_masks_sum + // tgc.real_in_asset_id_blinding_mask_x_amount_sum + return true; -#else - return true; -#endif } //---------------------------------------------------------------------------------------------------- @@ -421,4 +519,4 @@ namespace currency } -} \ No newline at end of file +} diff --git a/src/currency_core/currency_format_utils_transactions.h b/src/currency_core/currency_format_utils_transactions.h index f608b4eb..0ce53e85 100644 --- a/src/currency_core/currency_format_utils_transactions.h +++ b/src/currency_core/currency_format_utils_transactions.h @@ -344,7 +344,8 @@ namespace currency END_SERIALIZE() }; // struct tx_generation_context - bool validate_tx_output_details_againt_tx_generation_context(const transaction& tx, const tx_generation_context& gen_context); + bool validate_tx_details_against_tx_generation_context(const transaction& tx, const tx_generation_context& gen_context); + std::string transform_tx_to_str(const transaction& tx); transaction transform_str_to_tx(const std::string& tx_str); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 5effc4f1..6b746c8f 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -6060,8 +6060,8 @@ bool wallet2::get_ionic_swap_proposal_info(const wallet_public::ionic_swap_propo r = t_unserializable_object_from_blob(ionic_context, decrypted_raw_context); THROW_IF_FALSE_WALLET_INT_ERR_EX(r, "Failed to unserialize decrypted ionic_context"); - r = validate_tx_output_details_againt_tx_generation_context(tx, ionic_context.gen_context); - THROW_IF_FALSE_WALLET_INT_ERR_EX(r, "Failed to validate decrypted ionic_context"); + r = validate_tx_details_against_tx_generation_context(tx, ionic_context.gen_context); + THROW_IF_FALSE_WALLET_INT_ERR_EX(r, "validate_tx_details_against_tx_generation_context failed"); std::unordered_map amounts_provided_by_a; From c101a210104f5fb20c408cd3e597eccb60d2fdf3 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 25 Jun 2024 15:55:36 +0200 Subject: [PATCH 26/53] warning fixed --- src/wallet/wallet2.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 6b746c8f..16aabd4e 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -6099,7 +6099,7 @@ bool wallet2::get_ionic_swap_proposal_info(const wallet_public::ionic_swap_propo //THROW_IF_FALSE_WALLET_INT_ERR_EX(ionic_context.gen_context.input_amounts.size() == tx.vin.size(), "Tx gen context has mismatch with tx(amount != amount)"); for (i = 0; i != tx.vin.size(); i++) { - size_t mx = 0; + //size_t mx = 0; uint64_t amount = 0; crypto::public_key in_asset_id = currency::native_coin_asset_id; if (tx.vin[i].type() == typeid(txin_zc_input)) @@ -6107,12 +6107,12 @@ bool wallet2::get_ionic_swap_proposal_info(const wallet_public::ionic_swap_propo in_asset_id = ionic_context.gen_context.real_zc_ins_asset_ids[zc_current_index].to_public_key(); amount = ionic_context.gen_context.zc_input_amounts[zc_current_index]; zc_current_index++; - mx = boost::get(tx.vin[i]).key_offsets.size() - 1; + //mx = boost::get(tx.vin[i]).key_offsets.size() - 1; } else if (tx.vin[i].type() == typeid(txin_to_key)) { amount = boost::get(tx.vin[i]).amount; - mx = boost::get(tx.vin[i]).key_offsets.size() - 1; + //mx = boost::get(tx.vin[i]).key_offsets.size() - 1; } else { From 291d39383d4ff4b7bf348b98decfb671a32cd3f8 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Tue, 25 Jun 2024 21:20:19 +0400 Subject: [PATCH 27/53] fixed description in simplewallet(reported by Gonbatfire) --- src/simplewallet/simplewallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index fb1c3a61..3935cb4c 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -290,7 +290,7 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("start_mining", boost::bind(&simple_wallet::start_mining, this, ph::_1), "start_mining - Start mining in daemon"); m_cmd_binder.set_handler("stop_mining", boost::bind(&simple_wallet::stop_mining, this, ph::_1), "Stop mining in daemon"); m_cmd_binder.set_handler("refresh", boost::bind(&simple_wallet::refresh, this, ph::_1), "Resynchronize transactions and balance"); - m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, ph::_1), "[force_all] Show current wallet balance, with 'force_all' param it displays all assets without filtering against whitelists"); + m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, ph::_1), "[raw] Show current wallet balance, with 'raw' param it displays all assets without filtering against whitelists"); m_cmd_binder.set_handler("show_staking_history", boost::bind(&simple_wallet::show_staking_history, this, ph::_1), "show_staking_history [2] - Show staking transfers, if option provided - number of days for history to display"); m_cmd_binder.set_handler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, ph::_1), "incoming_transfers [available|unavailable] - Show incoming transfers - all of them or filter them by availability"); m_cmd_binder.set_handler("incoming_counts", boost::bind(&simple_wallet::show_incoming_transfers_counts, this, ph::_1), "incoming_transfers counts"); From d4d3ea1d2376ac0443142b37f1c02a385000ddc5 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 26 Jun 2024 14:56:37 +0200 Subject: [PATCH 28/53] unit_tests: p2p_client_version_test_1 fixed --- tests/unit_tests/p2p_client_version.cpp | 39 +++++++++++-------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/tests/unit_tests/p2p_client_version.cpp b/tests/unit_tests/p2p_client_version.cpp index 3761e36a..183f6d36 100644 --- a/tests/unit_tests/p2p_client_version.cpp +++ b/tests/unit_tests/p2p_client_version.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Zano Project +// Copyright (c) 2019-2024 Zano Project // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -9,35 +9,27 @@ TEST(p2p_client_version, test_1) { using namespace tools; - // good + // good (>= 2.x since HF4) ASSERT_TRUE(check_remote_client_version("10.101.999.28391[deadbeef31337-dirty]")); - ASSERT_TRUE(check_remote_client_version("1.1.9.237[aabcd]")); ASSERT_TRUE(check_remote_client_version("3.0.2.7[aa00bcd]")); - ASSERT_TRUE(check_remote_client_version("1.4.2.7[aabcd]")); - ASSERT_TRUE(check_remote_client_version("1.1.2.67[88f868c]")); - ASSERT_TRUE(check_remote_client_version("1.1.2.67[88f868c]")); - ASSERT_TRUE(check_remote_client_version("1.1.2.67[26c00a8]")); - ASSERT_TRUE(check_remote_client_version("1.1.2.67[26c00a8-dirty]")); - - ASSERT_TRUE(check_remote_client_version("1.1.0.65[40ba8cd]")); - ASSERT_TRUE(check_remote_client_version("1.1.0.63[b0f376b]")); - - ASSERT_TRUE(check_remote_client_version("1.1.0.58[14bd668]")); - ASSERT_TRUE(check_remote_client_version("1.1.0.58[9920eb7]")); - ASSERT_TRUE(check_remote_client_version("1.1.0.58[e0d4ad8]")); - - ASSERT_TRUE(check_remote_client_version("1.1.0.57[b77b915]")); - ASSERT_TRUE(check_remote_client_version("1.1.0.57[7dd61ae]")); - ASSERT_TRUE(check_remote_client_version("1.1.0.57[7dd61ae-dirty]")); - - ASSERT_TRUE(check_remote_client_version("1.1.0.57")); + ASSERT_TRUE(check_remote_client_version("2.0.0.000[a]")); + ASSERT_TRUE(check_remote_client_version("2.4.2.7[aabcd]")); + ASSERT_TRUE(check_remote_client_version("2.99.0.67[26c00a8-dirty]")); + ASSERT_TRUE(check_remote_client_version("4.0.0.0[7dd61ae-dirty]")); + ASSERT_TRUE(check_remote_client_version("5.0.0.0[7dd61ae-dirty]")); // bad ASSERT_FALSE(check_remote_client_version("")); ASSERT_FALSE(check_remote_client_version(" ")); + ASSERT_FALSE(check_remote_client_version(" ")); + ASSERT_FALSE(check_remote_client_version(" ")); + + ASSERT_FALSE(check_remote_client_version(".")); + ASSERT_FALSE(check_remote_client_version("..")); + ASSERT_FALSE(check_remote_client_version("...")); ASSERT_FALSE(check_remote_client_version("1.0.999")); @@ -48,6 +40,9 @@ TEST(p2p_client_version, test_1) ASSERT_FALSE(check_remote_client_version("1.0.40[469]")); ASSERT_FALSE(check_remote_client_version("1.0.39[f77f0d7]")); ASSERT_FALSE(check_remote_client_version("1.0.38[f77f0d7-dirty]")); - ASSERT_FALSE(check_remote_client_version("1.0.37[7dd61ae-dirty]")); + ASSERT_FALSE(check_remote_client_version("1.99.37[7dd61ae-dirty]")); ASSERT_FALSE(check_remote_client_version("0.0.500[000]")); + + ASSERT_FALSE(check_remote_client_version("a.1.9.237[aabcd]")); + ASSERT_FALSE(check_remote_client_version("x.0.57")); } From cee6e51cbb16be29d1de729150d6f05aef61d224 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 26 Jun 2024 15:35:52 +0200 Subject: [PATCH 29/53] unit_tests: tx_signatures_packing.1 fixed --- tests/unit_tests/basic_struct_packing.cpp | 32 +++++++++++++---------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/tests/unit_tests/basic_struct_packing.cpp b/tests/unit_tests/basic_struct_packing.cpp index 41b16705..86896933 100644 --- a/tests/unit_tests/basic_struct_packing.cpp +++ b/tests/unit_tests/basic_struct_packing.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022 Zano Project +// Copyright (c) 2022-2024 Zano Project // Copyright (c) 2012-2014 The Boolberry developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -80,7 +80,10 @@ TEST(tx_signatures_packing, 1) sigs.clear(); ASSERT_EQ(1, get_object_blobsize(sigs)); + // + // Notation: // v(x) = tools::get_varint_packed_size(x) + // { // empty NLSAG @@ -105,7 +108,7 @@ TEST(tx_signatures_packing, 1) // 128 10-ring NLSAGs // v(128) + 128 * (1 + v(10) + 10 * 2 * 32) = 82178 sigs.clear(); - NLSAG_sig nlsag = AUTO_VAL_INIT(nlsag); + NLSAG_sig nlsag{}; nlsag.s.resize(10); for(size_t i = 0; i < 128; ++i) sigs.push_back(nlsag); @@ -113,37 +116,38 @@ TEST(tx_signatures_packing, 1) ASSERT_EQ(82178, get_object_blobsize(sigs)); } - // the following tests cases should be redone + // the following tests cases should be redone, do we really need them? -- sowle // TODO @#@# { // empty ZC_sig - // v(1) + (1 + 32 + 32 + (1 + 10*32) + 32) = 99 + // v(1) + 1 * (1 + 32 + 32 + (1 + 32 + v(0)+0*2*32 + 32 + 32)) = 164 sigs.clear(); sigs.emplace_back(std::move(ZC_sig())); - ASSERT_EQ(99, t_serializable_object_to_blob(sigs).size()); - ASSERT_EQ(99, get_object_blobsize(sigs)); + ASSERT_EQ(164, t_serializable_object_to_blob(sigs).size()); + ASSERT_EQ(164, get_object_blobsize(sigs)); } { // 128 empty ZC_sigs - // v(128) + 128 * (1 + 32 + 32 + (v(0) + 0*32) + 32) = 12546 + // v(128) + 128 * (1 + 32 + 32 + (1 + 32 + v(0)+0*2*32 + 32 + 32)) = 20866 sigs.clear(); for(size_t i = 0; i < 128; ++i) sigs.emplace_back(std::move(ZC_sig())); - ASSERT_EQ(12546, t_serializable_object_to_blob(sigs).size()); - ASSERT_EQ(12546, get_object_blobsize(sigs)); + ASSERT_EQ(20866, t_serializable_object_to_blob(sigs).size()); + ASSERT_EQ(20866, get_object_blobsize(sigs)); } { // 128 10-ring ZC_sigs - // v(128) + 128 * (1 + 32 + 32 + (v(10) + 10*32) + 32) = 53506 (97 + (v(10) + 10*32)) - ZC_sig zc = AUTO_VAL_INIT(zc); - //zc.clsags_gg.r.resize(10); + // v(128) + 128 * (1 + 32 + 32 + (1 + 32 + v(10)+10*2*32 + 32 + 32)) = 102786 + ZC_sig zc{}; + zc.clsags_ggx.r_x.resize(10); + zc.clsags_ggx.r_g.resize(10); sigs.clear(); for(size_t i = 0; i < 128; ++i) sigs.emplace_back(zc); - ASSERT_EQ(53506, t_serializable_object_to_blob(sigs).size()); - ASSERT_EQ(53506, get_object_blobsize(sigs)); + ASSERT_EQ(102786, t_serializable_object_to_blob(sigs).size()); + ASSERT_EQ(102786, get_object_blobsize(sigs)); } } From da5c484025c7264fb4716b96d152c774bc11a926 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 26 Jun 2024 17:30:55 +0200 Subject: [PATCH 30/53] functional_tests/crypto_tests: all performance tests now have prefix "perf", all normal tests with "crypto" prefix will be run regularly since now --- tests/functional_tests/crypto_tests.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/functional_tests/crypto_tests.cpp b/tests/functional_tests/crypto_tests.cpp index 9515df91..546fff99 100644 --- a/tests/functional_tests/crypto_tests.cpp +++ b/tests/functional_tests/crypto_tests.cpp @@ -1,5 +1,5 @@ -// Copyright (c) 2020-2023 Zano Project -// Copyright (c) 2020-2023 sowle (val@zano.org, crypto.sowle@gmail.com) +// Copyright (c) 2020-2024 Zano Project +// Copyright (c) 2020-2024 sowle (val@zano.org, crypto.sowle@gmail.com) // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -975,7 +975,7 @@ TEST(crypto, scalar_basics) return true; } -TEST(crypto, sc_mul_performance) +TEST(perf, sc_mul) { std::vector scalars(100000); for (auto& s : scalars) @@ -1070,7 +1070,7 @@ TEST(crypto, hp) return true; } -TEST(crypto, cn_fast_hash_perf) +TEST(perf, cn_fast_hash) { //return true; const crypto::hash h_initial = *(crypto::hash*)(&scalar_t::random()); @@ -1157,7 +1157,7 @@ TEST(crypto, cn_fast_hash_perf) -TEST(crypto, sc_invert_performance) +TEST(perf, sc_invert) { std::vector scalars(10000); LOG_PRINT_L0("Running " << scalars.size() << " sc_invert tests..."); From e31e2730c91d433321bf573868924a904cdf3a49 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 26 Jun 2024 22:01:30 +0400 Subject: [PATCH 31/53] added missing documetation --- src/rpc/core_rpc_server_commands_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index f088ccc6..7c3e748f 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -1645,7 +1645,7 @@ namespace currency BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END - KV_SERIALIZE(blocks) DOC_DSCR("List of alternative blocks with detailed information, retrieved based on the specified parameters.") DOC_END + KV_SERIALIZE(blocks) DOC_DSCR("List of alternative blocks with detailed information, retrieved based on the specified parameters.") DOC_EXMP_AUTO(1) DOC_END END_KV_SERIALIZE_MAP() }; }; From 7ff58b6b182afe720fba853d3aef68cfea37582e Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 26 Jun 2024 22:29:58 +0400 Subject: [PATCH 32/53] added missing documetation - 2 --- src/rpc/core_rpc_server_commands_defs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 7c3e748f..31fe8295 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -1581,7 +1581,7 @@ namespace currency KV_SERIALIZE(already_generated_coins) DOC_DSCR("Total amount of coins generated in the blockchain up to this block.") DOC_END KV_SERIALIZE(this_block_fee_median) DOC_DSCR("Median transaction fee of the transactions within this block.") DOC_END KV_SERIALIZE(effective_fee_median) // TODO - KV_SERIALIZE(transactions_details) DOC_DSCR("Detailed information about each transaction included in the block.") DOC_END + KV_SERIALIZE(transactions_details) DOC_DSCR("Detailed information about each transaction included in the block.") DOC_EXMP_AUTO(1) DOC_END KV_SERIALIZE(type) DOC_DSCR("Type of the block.") DOC_END KV_SERIALIZE(is_orphan) DOC_DSCR("Indicates whether the block is an orphan.") DOC_END KV_SERIALIZE(miner_text_info) DOC_DSCR("Additional textual information provided by the miner of the block.") DOC_END @@ -1616,7 +1616,7 @@ namespace currency BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END - KV_SERIALIZE(blocks) DOC_DSCR("List of blocks with detailed information, starting from the specified height.") DOC_END + KV_SERIALIZE(blocks) DOC_DSCR("List of blocks with detailed information, starting from the specified height.") DOC_EXMP_AUTO(1) DOC_END END_KV_SERIALIZE_MAP() }; }; From 21aae4496c8025eb907aa4e566c2581939eb8660 Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 27 Jun 2024 16:08:04 +0200 Subject: [PATCH 33/53] DOC_EXMP_AGGR added --- contrib/epee/include/serialization/keyvalue_serialization.h | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/epee/include/serialization/keyvalue_serialization.h b/contrib/epee/include/serialization/keyvalue_serialization.h index 91f1aeda..134c477b 100644 --- a/contrib/epee/include/serialization/keyvalue_serialization.h +++ b/contrib/epee/include/serialization/keyvalue_serialization.h @@ -107,6 +107,7 @@ public: \ //#define DOC_EXMP_AUTO_2(arg_1, arg_2) , KV_MAKE_ALIAS_NAME() (arg_1, arg_2) #define DOC_END ); } #define DOC_EXMP_AUTO(...) , epee::create_t_object(__VA_ARGS__) +#define DOC_EXMP_AGGR(...) , epee::create_t_object(KV_MAKE_ALIAS_NAME(){__VA_ARGS__}) // Function template to create an object with forwarded constructor arguments From d2b60b0090616339e7f3a1b62d64d4a7a4f0c465 Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 27 Jun 2024 16:08:44 +0200 Subject: [PATCH 34/53] RPC API: added missing documentation examples --- src/currency_core/blockchain_storage_basic.h | 2 +- src/rpc/core_rpc_server_commands_defs.h | 32 ++++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/currency_core/blockchain_storage_basic.h b/src/currency_core/blockchain_storage_basic.h index 65c6862b..0013dc51 100644 --- a/src/currency_core/blockchain_storage_basic.h +++ b/src/currency_core/blockchain_storage_basic.h @@ -180,7 +180,7 @@ namespace currency BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(total_pos_blocks) DOC_DSCR("Number of blocks in a given range.") DOC_EXMP(87482) DOC_END - KV_SERIALIZE(votes) DOC_DSCR("Result of votes in a given range.") DOC_END + KV_SERIALIZE(votes) DOC_DSCR("Result of votes in a given range.") DOC_EXMP_AUTO(2) DOC_END END_KV_SERIALIZE_MAP() }; diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 31fe8295..99c913bf 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -89,7 +89,7 @@ namespace currency BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) DOC_DSCR("Status code, OK if succeeded.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END KV_SERIALIZE(error_code) DOC_DSCR("Error code, if there's any error (optional).") DOC_EXMP_AUTO() DOC_END - KV_SERIALIZE(aliases_que) DOC_DSCR("List of aliases from txs that are currently in the tx pool.") DOC_EXMP_AUTO() DOC_END + KV_SERIALIZE(aliases_que) DOC_DSCR("List of aliases from txs that are currently in the tx pool.") DOC_EXMP_AUTO(1) DOC_END END_KV_SERIALIZE_MAP() }; }; @@ -161,8 +161,8 @@ namespace currency uint64_t count = 100; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(offset) DOC_DSCR("Offset for the item to start copying") DOC_EXMP(0) DOC_END - KV_SERIALIZE(count) DOC_DSCR("Number of items to recieve") DOC_EXMP(100) DOC_END + KV_SERIALIZE(offset) DOC_DSCR("Offset for the item to start copying") DOC_EXMP(0) DOC_END + KV_SERIALIZE(count) DOC_DSCR("Number of items to recieve") DOC_EXMP(100) DOC_END END_KV_SERIALIZE_MAP() }; @@ -172,8 +172,8 @@ namespace currency std::list assets; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) DOC_DSCR("Status code of operation, OK if success") DOC_EXMP(API_RETURN_CODE_OK) DOC_END - KV_SERIALIZE(assets) DOC_DSCR("List of assets registered in Zano blockchain") DOC_EXMP_AUTO(1) DOC_END + KV_SERIALIZE(status) DOC_DSCR("Status code of operation, OK if success") DOC_EXMP(API_RETURN_CODE_OK) DOC_END + KV_SERIALIZE(assets) DOC_DSCR("List of assets registered in Zano blockchain") DOC_EXMP_AUTO(1) DOC_END END_KV_SERIALIZE_MAP() }; }; @@ -224,9 +224,9 @@ namespace currency std::string status; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(blocks) DOC_DSCR("Bunch of blocks") DOC_END - KV_SERIALIZE(start_height) DOC_DSCR("Starting height of the resulting bunch of blocks.") DOC_END - KV_SERIALIZE(current_height) DOC_DSCR("Current height of the blockchain.") DOC_END + KV_SERIALIZE(blocks) DOC_DSCR("Bunch of blocks") DOC_EXMP_AUTO(1) DOC_END + KV_SERIALIZE(start_height) DOC_DSCR("Starting height of the resulting bunch of blocks.") DOC_EXMP(2000000) DOC_END + KV_SERIALIZE(current_height) DOC_DSCR("Current height of the blockchain.") DOC_EXMP(2555000) DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -245,7 +245,7 @@ namespace currency std::list txs_hashes; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(txs_hashes) DOC_DSCR("List of transactions' IDs.") DOC_EXMP_AUTO() DOC_END // "146791c4f5ca94bcf423557e5eb859a3a69991bd33960d52f709d88bf5d1ac6d","ec4d913a40a9ac1fbd9d33b71ef507b5c85d1f503b89096618a18b08991b5171") DOC_END + KV_SERIALIZE(txs_hashes) DOC_DSCR("List of transactions' IDs.") DOC_EXMP_AGGR("146791c4f5ca94bcf423557e5eb859a3a69991bd33960d52f709d88bf5d1ac6d","ec4d913a40a9ac1fbd9d33b71ef507b5c85d1f503b89096618a18b08991b5171") DOC_END END_KV_SERIALIZE_MAP() }; @@ -257,7 +257,7 @@ namespace currency BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(txs_as_hex) DOC_DSCR("Transactions stored as blobs") DOC_EXMP_AUTO(1, "7d914497d91442f8f3c2268397d914497d91442f8f3c22683585eaa60b53757d49bf046a96269cef45c1bc9ff7300cc2f8f3c22683585eaa60b53757d49bf046a96269cef45c1bc9ff7300cc") DOC_END - KV_SERIALIZE(missed_tx) DOC_DSCR("Missed transactions hashes") DOC_EXMP_AUTO(1, "97d91442f8f3c22683585eaa60b53757d49bf046a96269cef45c1bc9ff7300cc") DOC_END + KV_SERIALIZE(missed_tx) DOC_DSCR("Missed transactions hashes") DOC_EXMP_AUTO(1, "ec4d913a40a9ac1fbd9d33b71ef507b5c85d1f503b89096618a18b08991b5171") DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -307,7 +307,7 @@ namespace currency BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(txs) DOC_DSCR("Transactions as blobs.") DOC_EXMP_AUTO(1, "7d914497d91442f8f3c2268397d914497d91442f8f3c22683585eaa60b53757d49bf046a96269cef45c1bc9ff7300cc2f8f3c22683585eaa60b53757d49bf046a96269cef45c1bc9ff7300cc") DOC_END - KV_SERIALIZE(tx_expiration_ts_median) DOC_DSCR("Timestamp median value of last TX_EXPIRATION_TIMESTAMP_CHECK_WINDOW blocks.") DOC_END + KV_SERIALIZE(tx_expiration_ts_median) DOC_DSCR("Timestamp median value of last TX_EXPIRATION_TIMESTAMP_CHECK_WINDOW blocks.") DOC_EXMP(1711021795) DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -321,7 +321,7 @@ namespace currency { std::list images; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(images) //DOC_DSCR("List of key images.") DOC_END + KV_SERIALIZE_CONTAINER_POD_AS_BLOB(images) //DOC_DSCR("List of key images.") DOC_EXMP_AGGR({{'\xd6', '\x32', '\x9b', '\x5b', '\x1f', '\x7c', '\x08', '\x05', '\xb5', '\xc3', '\x45', '\xf4', '\x95', '\x75', '\x54', '\x00', '\x2a', '\x2f', '\x55', '\x78', '\x45', '\xf6', '\x4d', '\x76', '\x45', '\xda', '\xe0', '\xe0', '\x51', '\xa6', '\x49', '\x8a'}}) DOC_END END_KV_SERIALIZE_MAP() }; @@ -374,8 +374,8 @@ namespace currency uint64_t i; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount) DOC_DSCR("The specific amount of output to query.") DOC_END - KV_SERIALIZE(i) DOC_DSCR("The global index of the output amount to be queried.") DOC_END + KV_SERIALIZE(amount) DOC_DSCR("The specific amount of output to query.") DOC_EXMP(3000000000000) DOC_END + KV_SERIALIZE(i) DOC_DSCR("The global index of the output amount to be queried.") DOC_EXMP(0) DOC_END END_KV_SERIALIZE_MAP() }; @@ -386,8 +386,8 @@ namespace currency uint64_t out_no; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_POD_AS_HEX_STRING(tx_id) DOC_DSCR("Transaction ID where the queried output is present, if found.") DOC_END - KV_SERIALIZE(out_no) DOC_DSCR("Local output index within the transaction.") DOC_END + KV_SERIALIZE_POD_AS_HEX_STRING(tx_id) DOC_DSCR("Transaction ID where the queried output is present, if found.") DOC_EXMP("a6e8da986858e6825fce7a192097e6afae4e889cabe853a9c29b964985b23da8") DOC_END + KV_SERIALIZE(out_no) DOC_DSCR("Local output index within the transaction.") DOC_EXMP(7) DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; From c26d449630db179929899b587a9bf07e67374713 Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 27 Jun 2024 19:38:19 +0200 Subject: [PATCH 35/53] RPC API: added missing documentation examples 2 --- src/rpc/core_rpc_server_commands_defs.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 99c913bf..a89bfb14 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -403,7 +403,7 @@ namespace currency crypto::hash ms_id; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_POD_AS_HEX_STRING(ms_id) DOC_DSCR("The multisig output's unique identifier (hash).") DOC_END + KV_SERIALIZE_POD_AS_HEX_STRING(ms_id) DOC_DSCR("The multisig output's unique identifier (hash).") DOC_EXMP("a6e8da986858e6825fce7a192097e6afae4e889cabe853a9c29b964985b23da8") DOC_END END_KV_SERIALIZE_MAP() }; @@ -414,8 +414,8 @@ namespace currency uint64_t out_no; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_POD_AS_HEX_STRING(tx_id) DOC_DSCR("Transaction ID where the multisig output is present, if found.")DOC_END - KV_SERIALIZE(out_no) DOC_DSCR("Local output index within the transaction.") DOC_END + KV_SERIALIZE_POD_AS_HEX_STRING(tx_id) DOC_DSCR("Transaction ID where the multisig output is present, if found.") DOC_EXMP("a88541e38d64f87c41b9153412d1d7667f6e4337fe429ed1374722355fa7b423") DOC_END + KV_SERIALIZE(out_no) DOC_DSCR("Local output index within the transaction.") DOC_EXMP(11) DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -432,10 +432,10 @@ namespace currency uint64_t height_upper_limit; // if nonzero, all the decoy outputs must be either older than, or the same age as this height bool use_forced_mix_outs; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amounts) DOC_DSCR("List of amounts for which decoy outputs are requested.") DOC_END - KV_SERIALIZE(decoys_count) DOC_DSCR("Number of decoy outputs required for each amount specified.") DOC_END - KV_SERIALIZE(height_upper_limit) DOC_DSCR("Maximum blockchain height from which decoys can be taken. If nonzero, decoys must be at this height or older.") DOC_END - KV_SERIALIZE(use_forced_mix_outs) DOC_DSCR("If true, only outputs with a 'mix_attr' greater than 0 are used as decoys.") DOC_END + KV_SERIALIZE(amounts) DOC_DSCR("List of amounts for which decoy outputs are requested.") DOC_EXMP_AGGR(0, 10000000000, 5000000000000) DOC_END + KV_SERIALIZE(decoys_count) DOC_DSCR("Number of decoy outputs required for each amount specified.") DOC_EXMP_AUTO(10) DOC_END + KV_SERIALIZE(height_upper_limit) DOC_DSCR("Maximum blockchain height from which decoys can be taken. If nonzero, decoys must be at this height or older.") DOC_EXMP_AUTO(2555000) DOC_END + KV_SERIALIZE(use_forced_mix_outs) DOC_DSCR("If true, only outputs with a 'mix_attr' greater than 0 are used as decoys.") DOC_EXMP_AUTO(false) DOC_END END_KV_SERIALIZE_MAP() }; From b51b26cb142615b9e321d4b219ddbf2a69978d19 Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 27 Jun 2024 20:01:57 +0200 Subject: [PATCH 36/53] ui update --- src/gui/qt-daemon/layout | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/qt-daemon/layout b/src/gui/qt-daemon/layout index fb814ffb..0710887a 160000 --- a/src/gui/qt-daemon/layout +++ b/src/gui/qt-daemon/layout @@ -1 +1 @@ -Subproject commit fb814ffb346375996dc2586d7e814f28bfe15ddd +Subproject commit 0710887ae3231d329092691f326d91d90662149e From 41f9302fce417b09831477b62b3d2f17b44c2bee Mon Sep 17 00:00:00 2001 From: zano build machine Date: Thu, 27 Jun 2024 21:03:11 +0300 Subject: [PATCH 37/53] === build number: 320 -> 321 === --- src/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h.in b/src/version.h.in index 6858efe8..d2dacde9 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -8,6 +8,6 @@ #define PROJECT_REVISION "0" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 320 +#define PROJECT_VERSION_BUILD_NO 321 #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 "]" From 05547c5c0d766417b875a20f836f3cab1d4c2114 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 27 Jun 2024 23:33:43 +0400 Subject: [PATCH 38/53] added LICENSE file to root folder --- LICENSE | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..fdb74465 --- /dev/null +++ b/LICENSE @@ -0,0 +1,9 @@ +Copyright (C) 2024 Zano project + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Zano project shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Zano project. \ No newline at end of file From 4e20dad9246d90a88562973063239cd1e754b7c5 Mon Sep 17 00:00:00 2001 From: sowle Date: Fri, 28 Jun 2024 19:51:28 +0200 Subject: [PATCH 39/53] RPC API: added missing documentation examples 3 --- src/rpc/core_rpc_server_commands_defs.h | 346 ++++++++++++------------ 1 file changed, 173 insertions(+), 173 deletions(-) diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index a89bfb14..9a89d043 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -469,7 +469,7 @@ namespace currency std::list outs; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount) DOC_DSCR("The amount for which decoys are returned.") DOC_END + KV_SERIALIZE(amount) DOC_DSCR("The amount for which decoys are returned.") DOC_EXMP_AUTO(10000000000) DOC_END KV_SERIALIZE_CONTAINER_POD_AS_BLOB(outs) //DOC_DSCR("List of 'out_entry' structures, serialized as a blob.") DOC_END END_KV_SERIALIZE_MAP() }; @@ -479,7 +479,7 @@ namespace currency std::vector outs; std::string status; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(outs) DOC_DSCR("List of 'outs_for_amount' structures, each containing decoys for a specific amount.") DOC_END + KV_SERIALIZE(outs) DOC_DSCR("List of 'outs_for_amount' structures, each containing decoys for a specific amount.") DOC_EXMP_AUTO(1) DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -495,8 +495,8 @@ namespace currency std::vector global_offsets; //[i] = global_index to pick up BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount) DOC_DSCR("If set to 0, only ZC outputs are considered. If nonzero, only old bare outputs are considered.") DOC_END - KV_SERIALIZE(global_offsets) DOC_DSCR("List of global indices for picking decoys. Each index corresponds to a potential decoy output.") DOC_END + KV_SERIALIZE(amount) DOC_DSCR("If set to 0, only ZC outputs are considered. If nonzero, only old bare outputs are considered.") DOC_EXMP_AUTO(0) DOC_END + KV_SERIALIZE(global_offsets) DOC_DSCR("List of global indices for picking decoys. Each index corresponds to a potential decoy output.") DOC_EXMP_AGGR(1, 3, 5928, 2811) DOC_END END_KV_SERIALIZE_MAP() }; @@ -508,10 +508,10 @@ namespace currency bool use_forced_mix_outs; uint64_t coinbase_percents; //from 0 to 100, estimate percents of coinbase outputs included in decoy sets BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amounts) DOC_DSCR("List of amount distributions specifying where to look for decoys, based on old bare outputs or ZC outputs.") DOC_END - KV_SERIALIZE(height_upper_limit) DOC_DSCR("Maximum blockchain height from which decoys can be taken. If nonzero, decoys must be at this height or older.") DOC_END - KV_SERIALIZE(use_forced_mix_outs) DOC_DSCR("If true, only outputs with a 'mix_attr' greater than 0 are used as decoys.") DOC_END - KV_SERIALIZE(coinbase_percents) DOC_DSCR("Specifies the estimated percentage of coinbase outputs to be included in the decoy sets, ranging from 0 to 100.") DOC_END + KV_SERIALIZE(amounts) DOC_DSCR("List of amount distributions specifying where to look for decoys, based on old bare outputs or ZC outputs.") DOC_EXMP_AUTO(1) DOC_END + KV_SERIALIZE(height_upper_limit) DOC_DSCR("Maximum blockchain height from which decoys can be taken. If nonzero, decoys must be at this height or older.") DOC_EXMP(2555000) DOC_END + KV_SERIALIZE(use_forced_mix_outs) DOC_DSCR("If true, only outputs with a 'mix_attr' greater than 0 are used as decoys.") DOC_EXMP(false) DOC_END + KV_SERIALIZE(coinbase_percents) DOC_DSCR("Specifies the estimated percentage of coinbase outputs to be included in the decoy sets, ranging from 0 to 100.") DOC_EXMP(15) DOC_END END_KV_SERIALIZE_MAP() }; @@ -529,9 +529,9 @@ namespace currency bool use_forced_mix_outs; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amounts) DOC_DSCR("List of amounts for which decoy outputs are requested.") DOC_END - KV_SERIALIZE(outs_count) DOC_DSCR("Number of decoy outputs requested for each amount.") DOC_END - KV_SERIALIZE(use_forced_mix_outs) DOC_DSCR("If true, only outputs with a 'mix_attr' greater than 0 are used as decoys.") DOC_END + KV_SERIALIZE(amounts) DOC_DSCR("List of amounts for which decoy outputs are requested.") DOC_EXMP_AGGR(0, 10000000000) DOC_END + KV_SERIALIZE(outs_count) DOC_DSCR("Number of decoy outputs requested for each amount.") DOC_EXMP(2) DOC_END + KV_SERIALIZE(use_forced_mix_outs) DOC_DSCR("If true, only outputs with a 'mix_attr' greater than 0 are used as decoys.") DOC_EXMP(false) DOC_END END_KV_SERIALIZE_MAP() }; @@ -549,7 +549,7 @@ namespace currency std::list outs; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount) DOC_DSCR("The amount for which decoys are returned.") DOC_END + KV_SERIALIZE(amount) DOC_DSCR("The amount for which decoys are returned.") DOC_EXMP(10000000000) DOC_END KV_SERIALIZE_CONTAINER_POD_AS_BLOB(outs) //DOC_DSCR("List of 'out_entry' structures serialized as a blob, representing the decoy outputs for the specified amount.") DOC_END END_KV_SERIALIZE_MAP() }; @@ -560,7 +560,7 @@ namespace currency std::string status; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(outs) DOC_DSCR("List of 'outs_for_amount' structures, each containing decoys for a specific amount.") DOC_END + KV_SERIALIZE(outs) DOC_DSCR("List of 'outs_for_amount' structures, each containing decoys for a specific amount.") DOC_EXMP_AUTO(1) DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -595,7 +595,7 @@ namespace currency explicit request(const transaction &); BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tx_as_hex) DOC_DSCR("The transaction data as a hexadecimal string, ready for network broadcast.") DOC_END + KV_SERIALIZE(tx_as_hex) DOC_DSCR("The transaction data as a hexadecimal string, ready for network broadcast.") DOC_EXMP("00018ed1535b8b4862e.....368cdc5a86") DOC_END END_KV_SERIALIZE_MAP() }; @@ -619,7 +619,7 @@ namespace currency std::vector txs_as_hex; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(txs_as_hex) DOC_DSCR("List of transactions as a hexadecimal strings.") DOC_END + KV_SERIALIZE(txs_as_hex) DOC_DSCR("List of transactions as a hexadecimal strings.") DOC_EXMP_AGGR("000535b8b2e.....3685a86", "00087368b2e.....349b77f") DOC_END END_KV_SERIALIZE_MAP() }; @@ -644,8 +644,8 @@ namespace currency uint64_t threads_count; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(miner_address) DOC_DSCR("The address where the mining rewards will be deposited.") DOC_END - KV_SERIALIZE(threads_count) DOC_DSCR("The number of CPU threads to use for mining.") DOC_END + KV_SERIALIZE(miner_address) DOC_DSCR("The address where the mining rewards will be deposited.") DOC_EXMP("ZxCSpsGGeJsS8fwvQ4HktDU3qBeauoJTR6j73jAWWZxFXdF7XTbGm4YfS2kXJmAP4Rf5BVsSQ9iZ45XANXEYsrLN2L2W77dH7") DOC_END + KV_SERIALIZE(threads_count) DOC_DSCR("The number of CPU threads to use for mining.") DOC_EXMP(2) DOC_END END_KV_SERIALIZE_MAP() }; @@ -850,7 +850,7 @@ namespace currency uint64_t flags; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(flags) DOC_DSCR("Combination of flags to request specific data elements that are computationally expensive to calculate.") DOC_END + KV_SERIALIZE(flags) DOC_DSCR("Combination of flags to request specific data elements that are computationally expensive to calculate.") DOC_EXMP(1048575) DOC_END END_KV_SERIALIZE_MAP() }; @@ -920,55 +920,55 @@ namespace currency BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END // Always calculated and provided fields - KV_SERIALIZE(height) DOC_DSCR("The current size of the blockchain, equal to the height of the top block plus one.") DOC_END - KV_SERIALIZE(pos_allowed) DOC_DSCR("Boolean value indicating whether PoS mining is currently allowed based on network rules and state.") DOC_END - KV_SERIALIZE(pos_difficulty) DOC_DSCR("Current difficulty for Proof of Stake mining.") DOC_END - KV_SERIALIZE(pow_difficulty) DOC_DSCR("Current difficulty for Proof of Work mining.") DOC_END - KV_SERIALIZE(tx_count) DOC_DSCR("Total number of transactions in the blockchain.") DOC_END - KV_SERIALIZE(tx_pool_size) DOC_DSCR("Number of transactions currently in the pool.") DOC_END - KV_SERIALIZE(alt_blocks_count) DOC_DSCR("Number of alternative blocks on the blockchain.") DOC_END - KV_SERIALIZE(outgoing_connections_count) DOC_DSCR("Number of outgoing P2P connections to other nodes.") DOC_END - KV_SERIALIZE(incoming_connections_count) DOC_DSCR("Number of incoming P2P connections established by other nodes.") DOC_END - KV_SERIALIZE(synchronized_connections_count) DOC_DSCR("Number of P2P connections to nodes that have a fully synchronized blockchain.") DOC_END - KV_SERIALIZE(white_peerlist_size) DOC_DSCR("Size of the white peer list, which includes addresses of reliable nodes.") DOC_END - KV_SERIALIZE(grey_peerlist_size) DOC_DSCR("Size of the grey peer list, which includes addresses of nodes with less consistent availability.") DOC_END + KV_SERIALIZE(height) DOC_DSCR("The current size of the blockchain, equal to the height of the top block plus one.") DOC_EXMP(2555000) DOC_END + KV_SERIALIZE(pos_allowed) DOC_DSCR("Boolean value indicating whether PoS mining is currently allowed based on network rules and state.") DOC_EXMP(true) DOC_END + KV_SERIALIZE(pos_difficulty) DOC_DSCR("Current difficulty for Proof of Stake mining.") DOC_EXMP("1848455949616658404658") DOC_END + KV_SERIALIZE(pow_difficulty) DOC_DSCR("Current difficulty for Proof of Work mining.") DOC_EXMP(12777323347117) DOC_END + KV_SERIALIZE(tx_count) DOC_DSCR("Total number of transactions in the blockchain.") DOC_EXMP(767742) DOC_END + KV_SERIALIZE(tx_pool_size) DOC_DSCR("Number of transactions currently in the pool.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(alt_blocks_count) DOC_DSCR("Number of alternative blocks on the blockchain.") DOC_EXMP(99) DOC_END + KV_SERIALIZE(outgoing_connections_count) DOC_DSCR("Number of outgoing P2P connections to other nodes.") DOC_EXMP(8) DOC_END + KV_SERIALIZE(incoming_connections_count) DOC_DSCR("Number of incoming P2P connections established by other nodes.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(synchronized_connections_count) DOC_DSCR("Number of P2P connections to nodes that have a fully synchronized blockchain.") DOC_EXMP(8) DOC_END + KV_SERIALIZE(white_peerlist_size) DOC_DSCR("Size of the white peer list, which includes addresses of reliable nodes.") DOC_EXMP(12) DOC_END + KV_SERIALIZE(grey_peerlist_size) DOC_DSCR("Size of the grey peer list, which includes addresses of nodes with less consistent availability.") DOC_EXMP(321) DOC_END KV_SERIALIZE(current_blocks_median) // TODO - KV_SERIALIZE(alias_count) DOC_DSCR("The total number of unique aliases registered on the blockchain. Aliases are alternate, human-readable names associated with addresses.") DOC_END - KV_SERIALIZE(current_max_allowed_block_size) DOC_DSCR("Current maximum allowed cummulative block size in bytes.") DOC_END - KV_SERIALIZE(is_hardfok_active) DOC_DSCR("A list of boolean values indicating whether each corresponding hardfork is active. For example, a list 'true, true, false' indicates that the first hardfork is activated, while the second is not. Hardfork #0 is always active as it is a stub.") DOC_END - KV_SERIALIZE(daemon_network_state) DOC_DSCR("Current network state of the daemon, which could be connecting, synchronizing, online, loading core, internal error, unloading core, or downloading database.") DOC_END - KV_SERIALIZE(synchronization_start_height) DOC_DSCR("Blockchain height at which the current synchronization process started. Indicates the starting point for catching up to the network's latest state.") DOC_END - KV_SERIALIZE(max_net_seen_height) DOC_DSCR("Maximum blockchain height observed in the network by this node.") DOC_END - KV_SERIALIZE(default_fee) DOC_DSCR("Default fee for transactions.") DOC_END - KV_SERIALIZE(minimum_fee) DOC_DSCR("Minimum fee for transactions.") DOC_END - KV_SERIALIZE(mi) DOC_DSCR("The most recent mainterner's info.") DOC_END + KV_SERIALIZE(alias_count) DOC_DSCR("The total number of unique aliases registered on the blockchain. Aliases are alternate, human-readable names associated with addresses.") DOC_EXMP(1653) DOC_END + KV_SERIALIZE(current_max_allowed_block_size) DOC_DSCR("Current maximum allowed cummulative block size in bytes.") DOC_EXMP(250000) DOC_END + KV_SERIALIZE(is_hardfok_active) DOC_DSCR("A list of boolean values indicating whether each corresponding hardfork is active. For example, a list 'true, true, false' indicates that the first hardfork is activated, while the second is not. Hardfork #0 is always active as it is a stub.") DOC_EXMP_AGGR(true,true,true,true,true,false) DOC_END + KV_SERIALIZE(daemon_network_state) DOC_DSCR("Current network state of the daemon, which could be connecting, synchronizing, online, loading core, internal error, unloading core, or downloading database.") DOC_EXMP(2) DOC_END + KV_SERIALIZE(synchronization_start_height) DOC_DSCR("Blockchain height at which the current synchronization process started. Indicates the starting point for catching up to the network's latest state.") DOC_EXMP(2555000) DOC_END + KV_SERIALIZE(max_net_seen_height) DOC_DSCR("Maximum blockchain height observed in the network by this node.") DOC_EXMP(2555743) DOC_END + KV_SERIALIZE(default_fee) DOC_DSCR("Default fee for transactions.") DOC_EXMP(10000000000) DOC_END + KV_SERIALIZE(minimum_fee) DOC_DSCR("Minimum fee for transactions.") DOC_EXMP(10000000000) DOC_END + KV_SERIALIZE(mi) DOC_DSCR("The most recent mainterner's info.") DOC_EXMP_AUTO() DOC_END // Fields dependent on flags for their inclusion - KV_SERIALIZE(net_time_delta_median) DOC_DSCR("A value of 0 indicates no time synchronization issues, while a value of 1 indicates the presence of time sync issues. Only available if the COMMAND_RPC_GET_INFO_FLAG_NET_TIME_DELTA_MEDIAN flag is set.") DOC_END - KV_SERIALIZE(current_network_hashrate_50)DOC_DSCR("The PoW hash rate calculated over the last 50 blocks of any type. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_CURRENT_NETWORK_HASHRATE_50 flag is set.") DOC_END - KV_SERIALIZE(current_network_hashrate_350) DOC_DSCR("The PoW hash rate calculated over the last 350 blocks of any type. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_CURRENT_NETWORK_HASHRATE_350 flag is set.") DOC_END - KV_SERIALIZE(seconds_for_10_blocks) DOC_DSCR("The time period in seconds between the most recent block and the 10th block older. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_SECONDS_FOR_10_BLOCKS flag is set.") DOC_END - KV_SERIALIZE(seconds_for_30_blocks) DOC_DSCR("The time period in seconds between the most recent block and the 30th block older. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_SECONDS_FOR_30_BLOCKS flag is set.") DOC_END - KV_SERIALIZE(transactions_cnt_per_day) DOC_DSCR("The number of non-mining transactions recorded over the last 24 hours. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_TRANSACTIONS_DAILY_STAT flag is set.") DOC_END - KV_SERIALIZE(transactions_volume_per_day)DOC_DSCR("The total sum of input amounts from all non-mining transactions over the last 24 hours. Only old bare inputs with explicit amounts are considered. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_TRANSACTIONS_DAILY_STAT flag is set.") DOC_END - KV_SERIALIZE(last_pos_timestamp) DOC_DSCR("The timestamp of the most recent PoS block. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_LAST_POS_TIMESTAMP flag is set.") DOC_END - KV_SERIALIZE(last_pow_timestamp) DOC_DSCR("The timestamp of the most recent PoW block. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_LAST_POW_TIMESTAMP flag is set.") DOC_END - KV_SERIALIZE(total_coins) DOC_DSCR("The total amount of all emitted coins in the system. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS flag is set.") DOC_END - KV_SERIALIZE(last_block_size) DOC_DSCR("The size of the last block in bytes. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_LAST_BLOCK_SIZE flag is set.") DOC_END - KV_SERIALIZE(tx_count_in_last_block) DOC_DSCR("The number of non-mining transactions in the last block. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_TX_COUNT_IN_LAST_BLOCK flag is set.") DOC_END - KV_SERIALIZE(pos_sequence_factor) DOC_DSCR("The current PoS sequence factor, representing the number of consecutive PoS blocks. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_POS_SEQUENCE_FACTOR flag is set.") DOC_END - KV_SERIALIZE(pow_sequence_factor) DOC_DSCR("The current PoW sequence factor, representing the number of consecutive PoW blocks. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_POW_SEQUENCE_FACTOR flag is set.") DOC_END - KV_SERIALIZE(block_reward) DOC_DSCR("The base block reward that is effective for the next block. Calculated only if either COMMAND_RPC_GET_INFO_FLAG_POS_DIFFICULTY or COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS flag is set.") DOC_END - KV_SERIALIZE(last_block_total_reward) DOC_DSCR("Reward for the last block, including base reward and transaction fees. Calculated only if either COMMAND_RPC_GET_INFO_FLAG_POS_DIFFICULTY or COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS flag is set.") DOC_END - KV_SERIALIZE(pos_diff_total_coins_rate) DOC_DSCR("PoS difficulty divided by the total amount of all coins in the system minus a premined amount (17,517,203). Calculated only if either COMMAND_RPC_GET_INFO_FLAG_POS_DIFFICULTY or COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS flag is set.") DOC_END - KV_SERIALIZE(last_block_timestamp) DOC_DSCR("Timestamp of the last block. Calculated only if either COMMAND_RPC_GET_INFO_FLAG_POS_DIFFICULTY or COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS flag is set.") DOC_END - KV_SERIALIZE(last_block_hash) DOC_DSCR("Hash of the last block. Calculated only if either COMMAND_RPC_GET_INFO_FLAG_POS_DIFFICULTY or COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS flag is set.") DOC_END - KV_SERIALIZE(pos_block_ts_shift_vs_actual) DOC_DSCR("The difference between the timestamp used in the last PoS block for mining purposes and its actual timestamp as stored in the miner's transaction extra data. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_POS_BLOCK_TS_SHIFT_VS_ACTUAL flag is set.") DOC_END - KV_SERIALIZE(outs_stat) DOC_DSCR("Statistics for the number of outputs that have a specific amount. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_OUTS_STAT flag is set.") DOC_END - KV_SERIALIZE(performance_data) DOC_DSCR("Detailed technical performance data intended for developers. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_PERFORMANCE flag is set.") DOC_END - KV_SERIALIZE(tx_pool_performance_data) DOC_DSCR("Detailed technical performance data intended for developers. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_PERFORMANCE flag is set.") DOC_END - KV_SERIALIZE(offers_count) DOC_DSCR("Current number of offers in the offers service. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_PERFORMANCE flag is set.") DOC_END - KV_SERIALIZE(expiration_median_timestamp)DOC_DSCR("Median of timestamps of the last N blocks, used to determine the expiration status of transactions. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_EXPIRATIONS_MEDIAN flag is set.") DOC_END + KV_SERIALIZE(net_time_delta_median) DOC_DSCR("A value of 0 indicates no time synchronization issues, while a value of 1 indicates the presence of time sync issues. Only available if the COMMAND_RPC_GET_INFO_FLAG_NET_TIME_DELTA_MEDIAN flag is set.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(current_network_hashrate_50)DOC_DSCR("The PoW hash rate calculated over the last 50 blocks of any type. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_CURRENT_NETWORK_HASHRATE_50 flag is set.") DOC_EXMP(109575236643) DOC_END + KV_SERIALIZE(current_network_hashrate_350) DOC_DSCR("The PoW hash rate calculated over the last 350 blocks of any type. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_CURRENT_NETWORK_HASHRATE_350 flag is set.") DOC_EXMP(107939216153) DOC_END + KV_SERIALIZE(seconds_for_10_blocks) DOC_DSCR("The time period in seconds between the most recent block and the 10th block older. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_SECONDS_FOR_10_BLOCKS flag is set.") DOC_EXMP(476) DOC_END + KV_SERIALIZE(seconds_for_30_blocks) DOC_DSCR("The time period in seconds between the most recent block and the 30th block older. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_SECONDS_FOR_30_BLOCKS flag is set.") DOC_EXMP(1264) DOC_END + KV_SERIALIZE(transactions_cnt_per_day) DOC_DSCR("The number of non-mining transactions recorded over the last 24 hours. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_TRANSACTIONS_DAILY_STAT flag is set.") DOC_EXMP(1325) DOC_END + KV_SERIALIZE(transactions_volume_per_day)DOC_DSCR("The total sum of input amounts from all non-mining transactions over the last 24 hours. Only old bare inputs with explicit amounts are considered. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_TRANSACTIONS_DAILY_STAT flag is set.") DOC_EXMP(6615220203700000) DOC_END + KV_SERIALIZE(last_pos_timestamp) DOC_DSCR("The timestamp of the most recent PoS block. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_LAST_POS_TIMESTAMP flag is set.") DOC_EXMP(1719585105) DOC_END + KV_SERIALIZE(last_pow_timestamp) DOC_DSCR("The timestamp of the most recent PoW block. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_LAST_POW_TIMESTAMP flag is set.") DOC_EXMP(1719586493) DOC_END + KV_SERIALIZE(total_coins) DOC_DSCR("The total amount of all emitted coins in the system. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS flag is set.") DOC_EXMP("14308874719144585856") DOC_END + KV_SERIALIZE(last_block_size) DOC_DSCR("The size of the last block in bytes. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_LAST_BLOCK_SIZE flag is set.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(tx_count_in_last_block) DOC_DSCR("The number of non-mining transactions in the last block. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_TX_COUNT_IN_LAST_BLOCK flag is set.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(pos_sequence_factor) DOC_DSCR("The current PoS sequence factor, representing the number of consecutive PoS blocks. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_POS_SEQUENCE_FACTOR flag is set.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(pow_sequence_factor) DOC_DSCR("The current PoW sequence factor, representing the number of consecutive PoW blocks. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_POW_SEQUENCE_FACTOR flag is set.") DOC_EXMP(1) DOC_END + KV_SERIALIZE(block_reward) DOC_DSCR("The base block reward that is effective for the next block. Calculated only if either COMMAND_RPC_GET_INFO_FLAG_POS_DIFFICULTY or COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS flag is set.") DOC_EXMP(1000000000000) DOC_END + KV_SERIALIZE(last_block_total_reward) DOC_DSCR("Reward for the last block, including base reward and transaction fees. Calculated only if either COMMAND_RPC_GET_INFO_FLAG_POS_DIFFICULTY or COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS flag is set.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(pos_diff_total_coins_rate) DOC_DSCR("PoS difficulty divided by the total amount of all coins in the system minus a premined amount (17,517,203). Calculated only if either COMMAND_RPC_GET_INFO_FLAG_POS_DIFFICULTY or COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS flag is set.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(last_block_timestamp) DOC_DSCR("Timestamp of the last block. Calculated only if either COMMAND_RPC_GET_INFO_FLAG_POS_DIFFICULTY or COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS flag is set.") DOC_EXMP(1719586493) DOC_END + KV_SERIALIZE(last_block_hash) DOC_DSCR("Hash of the last block. Calculated only if either COMMAND_RPC_GET_INFO_FLAG_POS_DIFFICULTY or COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS flag is set.") DOC_EXMP("153af86fd0d7d0a427526258e30505a4d21b8f77261f5276c7669e0a6c83efa0") DOC_END + KV_SERIALIZE(pos_block_ts_shift_vs_actual) DOC_DSCR("The difference between the timestamp used in the last PoS block for mining purposes and its actual timestamp as stored in the miner's transaction extra data. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_POS_BLOCK_TS_SHIFT_VS_ACTUAL flag is set.") DOC_EXMP(-1387) DOC_END + KV_SERIALIZE(outs_stat) DOC_DSCR("Statistics for the number of outputs that have a specific amount. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_OUTS_STAT flag is set.") DOC_EXMP_AUTO() DOC_END + KV_SERIALIZE(performance_data) DOC_DSCR("Detailed technical performance data intended for developers. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_PERFORMANCE flag is set.") DOC_EXMP_AUTO() DOC_END + KV_SERIALIZE(tx_pool_performance_data) DOC_DSCR("Detailed technical performance data intended for developers. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_PERFORMANCE flag is set.") DOC_EXMP_AUTO() DOC_END + KV_SERIALIZE(offers_count) DOC_DSCR("Current number of offers in the offers service. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_PERFORMANCE flag is set.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(expiration_median_timestamp)DOC_DSCR("Median of timestamps of the last N blocks, used to determine the expiration status of transactions. This information is only provided if the COMMAND_RPC_GET_INFO_FLAG_EXPIRATIONS_MEDIAN flag is set.") DOC_EXMP(1719585827) DOC_END END_KV_SERIALIZE_MAP() }; }; @@ -1011,7 +1011,7 @@ namespace currency std::string status; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(count) DOC_DSCR("The total number of blocks in the blockchain, equivalent to the top block's height plus one.") DOC_END + KV_SERIALIZE(count) DOC_DSCR("The total number of blocks in the blockchain, equivalent to the top block's height plus one.") DOC_EXMP(2697388) DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1044,12 +1044,12 @@ namespace currency bool pos_block; // is pos block BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_BLOB_AS_HEX_STRING(explicit_transaction) DOC_DSCR("A transaction blob that must be explicitly included in the block.") DOC_END - KV_SERIALIZE(extra_text) DOC_DSCR("Arbitrary data added to the extra field of the miner transaction.") DOC_END - KV_SERIALIZE(wallet_address) DOC_DSCR("Address where mining rewards will be deposited.") DOC_END + KV_SERIALIZE_BLOB_AS_HEX_STRING(explicit_transaction) DOC_DSCR("A transaction blob that must be explicitly included in the block.") DOC_EXMP("5fa8eaaf231a305053260ff91d69c6ef1ecbd0f5") DOC_END + KV_SERIALIZE(extra_text) DOC_DSCR("Arbitrary data added to the extra field of the miner transaction.") DOC_EXMP("OMG, you can't just ask people why they're PoW-maxi") DOC_END + KV_SERIALIZE(wallet_address) DOC_DSCR("Address where mining rewards will be deposited.") DOC_EXMP("ZxCSpsGGeJsS8fwvQ4HktDU3qBeauoJTR6j73jAWWZxFXdF7XTbGm4YfS2kXJmAP4Rf5BVsSQ9iZ45XANXEYsrLN2L2W77dH7") DOC_END KV_SERIALIZE(stakeholder_address) DOC_DSCR("Address where the stake is returned for PoS blocks (usually the same as 'wallet_address').") DOC_END KV_SERIALIZE(pe) DOC_DSCR("PoS entry details, relevant only for PoS block generation.") DOC_END - KV_SERIALIZE(pos_block) DOC_DSCR("Flag indicating whether the block is a PoS block.") DOC_END + KV_SERIALIZE(pos_block) DOC_DSCR("Flag indicating whether the block is a PoS block.") DOC_EXMP(false) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1067,15 +1067,15 @@ namespace currency std::string status; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(difficulty) DOC_DSCR("The mining difficulty targeted by the block template.") DOC_END - KV_SERIALIZE(height) DOC_DSCR("The height of the block template in the blockchain.") DOC_END - KV_SERIALIZE_POD_AS_HEX_STRING(seed) DOC_DSCR("Seed value for the ProgPoWZ mining algorithm's epoch.") DOC_END - KV_SERIALIZE(blocktemplate_blob) DOC_DSCR("Serialized block template blob.") DOC_END - KV_SERIALIZE(prev_hash) DOC_DSCR("Hash of the previous block in the chain.") DOC_END - KV_SERIALIZE(miner_tx_tgc) DOC_DSCR("Miner transaction generation context. Intended for PoS blocks and Zarcanum.") DOC_END - KV_SERIALIZE(block_reward_without_fee) DOC_DSCR("Base block reward excluding any transaction fees.") DOC_END - KV_SERIALIZE(block_reward) DOC_DSCR("Total block reward, including transaction fees if they are given to the miner (legacy), or the base reward if fees are burnt (current state).") DOC_END - KV_SERIALIZE(txs_fee) DOC_DSCR("Total fees from transactions included in the block.") DOC_END + KV_SERIALIZE(difficulty) DOC_DSCR("The mining difficulty targeted by the block template.") DOC_EXMP("12936195379842") DOC_END + KV_SERIALIZE(height) DOC_DSCR("The height of the block template in the blockchain.") DOC_EXMP(2555002) DOC_END + KV_SERIALIZE_POD_AS_HEX_STRING(seed) DOC_DSCR("Seed value for the ProgPoWZ mining algorithm's epoch.") DOC_EXMP("0518e1373ff88ccabb28493cac10cb0731313135d880dae0d846be6016ab9acf") DOC_END + KV_SERIALIZE(blocktemplate_blob) DOC_DSCR("Serialized block template blob.") DOC_EXMP("030000000000000000ae73338b792......6258a2b5ee340700") DOC_END + KV_SERIALIZE(prev_hash) DOC_DSCR("Hash of the previous block in the chain.") DOC_EXMP("ae73338b7927df71b6ed477937625c230172219306750ba97995fb5109dda703") DOC_END + KV_SERIALIZE(miner_tx_tgc) DOC_DSCR("Miner transaction generation context. Intended for PoS blocks and Zarcanum.") DOC_EXMP_AUTO() DOC_END + KV_SERIALIZE(block_reward_without_fee) DOC_DSCR("Base block reward excluding any transaction fees.") DOC_EXMP(1000000000000) DOC_END + KV_SERIALIZE(block_reward) DOC_DSCR("Total block reward, including transaction fees if they are given to the miner (legacy), or the base reward if fees are burnt (current state).") DOC_EXMP(1000000000000) DOC_END + KV_SERIALIZE(txs_fee) DOC_DSCR("Total fees from transactions included in the block.") DOC_EXMP(0) DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1111,8 +1111,8 @@ namespace currency std::list explicit_txs; //hex encoded tx blobs BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_BLOB_AS_HEX_STRING(b) DOC_DSCR("Hex-encoded serialized block.") DOC_END - KV_SERIALIZE(explicit_txs) DOC_DSCR("List of hex-encoded transactions to be explicitly included in the block.") DOC_END + KV_SERIALIZE_BLOB_AS_HEX_STRING(b) DOC_DSCR("Hex-encoded serialized block.") DOC_EXMP("030000000000000000ae73338b7926258a2b5ee340700") DOC_END + KV_SERIALIZE(explicit_txs) DOC_DSCR("List of hex-encoded transactions to be explicitly included in the block.") DOC_EXMP_AGGR({"6258a2b5ee7a9c20"}, {"8e0f0a2cee340700"}) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1143,17 +1143,17 @@ namespace currency uint64_t reward; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(major_version) DOC_DSCR("Major version of the block.") DOC_END - KV_SERIALIZE(minor_version) DOC_DSCR("Minor version of the block.") DOC_END - KV_SERIALIZE(timestamp) DOC_DSCR("Timestamp of the block creation.") DOC_END - KV_SERIALIZE(prev_hash) DOC_DSCR("Hash of the previous block in the chain.") DOC_END - KV_SERIALIZE(nonce) DOC_DSCR("Nonce used for generating the block to meet the network difficulty.") DOC_END - KV_SERIALIZE(orphan_status) DOC_DSCR("Indicates if the block is an orphan (true) or a normal block (false).") DOC_END - KV_SERIALIZE(height) DOC_DSCR("Height of the block in the blockchain.") DOC_END - KV_SERIALIZE(depth) DOC_DSCR("Depth of the block in the blockchain. Depth 0 indicates the most recent block.") DOC_END - KV_SERIALIZE(hash) DOC_DSCR("Hash of the block.") DOC_END - KV_SERIALIZE(difficulty) DOC_DSCR("Network difficulty target that the block met.") DOC_END - KV_SERIALIZE(reward) DOC_DSCR("Total mining reward of the block including transaction fees (if applicable).") DOC_END + KV_SERIALIZE(major_version) DOC_DSCR("Major version of the block.") DOC_EXMP(3) DOC_END + KV_SERIALIZE(minor_version) DOC_DSCR("Minor version of the block.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(timestamp) DOC_DSCR("Timestamp of the block creation.") DOC_EXMP(1719588270) DOC_END + KV_SERIALIZE(prev_hash) DOC_DSCR("Hash of the previous block in the chain.") DOC_EXMP("a1b4359c02985720b0cf542678e08f0d4075e518fbd0cd54bd280269545e0e6f") DOC_END + KV_SERIALIZE(nonce) DOC_DSCR("Nonce used for generating the block to meet the network difficulty.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(orphan_status) DOC_DSCR("Indicates if the block is an orphan (true) or a normal block (false).") DOC_EXMP(false) DOC_END + KV_SERIALIZE(height) DOC_DSCR("Height of the block in the blockchain.") DOC_EXMP(2697404) DOC_END + KV_SERIALIZE(depth) DOC_DSCR("Depth of the block in the blockchain. Depth 0 indicates the most recent block.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(hash) DOC_DSCR("Hash of the block.") DOC_EXMP("f5df39c4b1590394976aa6e72f04df7836e22dbdfc1e6f61f6cc1b624d83cd94") DOC_END + KV_SERIALIZE(difficulty) DOC_DSCR("Network difficulty target that the block met.") DOC_EXMP("1849593878843995770114") DOC_END + KV_SERIALIZE(reward) DOC_DSCR("Total mining reward of the block including transaction fees (if applicable).") DOC_EXMP(0) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1168,7 +1168,7 @@ namespace currency block_header_response block_header; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(block_header) + KV_SERIALIZE(block_header) DOC_DSCR("Detailed header information of the block.") DOC_EXMP_AUTO() DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1186,7 +1186,7 @@ namespace currency std::string hash; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(hash) DOC_DSCR("The hash of the block for which the header information is being requested.") DOC_END + KV_SERIALIZE(hash) DOC_DSCR("The hash of the block for which the header information is being requested.") DOC_EXMP("a1b4359c02985720b0cf542678e08f0d4075e518fbd0cd54bd280269545e0e6f") DOC_END END_KV_SERIALIZE_MAP() }; @@ -1196,7 +1196,7 @@ namespace currency block_header_response block_header; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(block_header) DOC_DSCR("Detailed header information of the block.") DOC_END + KV_SERIALIZE(block_header) DOC_DSCR("Detailed header information of the block.") DOC_EXMP_AUTO() DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1213,7 +1213,7 @@ namespace currency uint64_t height; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(height) DOC_DSCR("The height of the block for which the header information is being requested.") DOC_END + KV_SERIALIZE(height) DOC_DSCR("The height of the block for which the header information is being requested.") DOC_EXMP(2555000) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1223,7 +1223,7 @@ namespace currency block_header_response block_header; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(block_header) DOC_DSCR("Detailed header information of the block.") DOC_END + KV_SERIALIZE(block_header) DOC_DSCR("Detailed header information of the block.") DOC_EXMP_AUTO() DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1239,7 +1239,7 @@ namespace currency { std::string alias; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(alias) DOC_DSCR("The alias name for which details are being requested.") DOC_END + KV_SERIALIZE(alias) DOC_DSCR("The alias name for which details are being requested.") DOC_EXMP("gigabyted") DOC_END END_KV_SERIALIZE_MAP() }; @@ -1249,7 +1249,7 @@ namespace currency std::string status; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(alias_details) DOC_DSCR("Contains the detailed information about the specified alias, including the associated wallet address, tracking key, comment etc..") DOC_END + KV_SERIALIZE(alias_details) DOC_DSCR("Contains the detailed information about the specified alias, including the associated wallet address, tracking key, comment etc..") DOC_EXMP_AUTO() DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1265,7 +1265,7 @@ namespace currency { std::string alias; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(alias) DOC_DSCR("The alias name for which the registration cost is being queried.") DOC_END + KV_SERIALIZE(alias) DOC_DSCR("The alias name for which the registration cost is being queried.") DOC_EXMP("zxdya6q6whzwqjkmtcsjpc3ku") DOC_END END_KV_SERIALIZE_MAP() }; @@ -1275,7 +1275,7 @@ namespace currency std::string status; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(reward) DOC_DSCR("The registration cost for the specified alias.") DOC_END + KV_SERIALIZE(reward) DOC_DSCR("The registration cost for the specified alias.") DOC_EXMP(100000000000) DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1299,7 +1299,7 @@ namespace currency std::string status; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(aliases) DOC_DSCR("List of alias_rpc_details objects, each containing information about an individual alias.") DOC_END + KV_SERIALIZE(aliases) DOC_DSCR("List of alias_rpc_details objects, each containing information about an individual alias.") DOC_EXMP_AUTO(2) DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1317,8 +1317,8 @@ namespace currency uint64_t count; // The number of aliases to retrieve. BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(offset) DOC_DSCR("The offset in the list of all aliases from which to start retrieving.") DOC_END - KV_SERIALIZE(count) DOC_DSCR("The number of aliases to retrieve from the specified offset.") DOC_END + KV_SERIALIZE(offset) DOC_DSCR("The offset in the list of all aliases from which to start retrieving.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(count) DOC_DSCR("The number of aliases to retrieve from the specified offset.") DOC_EXMP(2) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1328,7 +1328,7 @@ namespace currency std::string status; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(aliases) DOC_DSCR("List of alias_rpc_details objects, each containing information about an individual alias retrieved based on the request parameters.") DOC_END + KV_SERIALIZE(aliases) DOC_DSCR("List of alias_rpc_details objects, each containing information about an individual alias retrieved based on the request parameters.") DOC_EXMP_AUTO(2) DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1348,7 +1348,7 @@ namespace currency std::string status; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(alias_info_list) DOC_DSCR("List of alias_rpc_details objects, each containing detailed information about each alias registered to the specified address.") DOC_END + KV_SERIALIZE(alias_info_list) DOC_DSCR("List of alias_rpc_details objects, each containing detailed information about each alias registered to the specified address.") DOC_EXMP_AUTO(1) DOC_END KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1387,7 +1387,7 @@ namespace currency std::list tx_to_remove; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tx_to_remove) DOC_DSCR("List of transaction IDs that are to be removed from the transaction pool.") DOC_END + KV_SERIALIZE(tx_to_remove) DOC_DSCR("List of transaction IDs that are to be removed from the transaction pool.") DOC_EXMP_AGGR("c5efacd06128fc5a73f58392c84534cd1a146de7d47ffbe770486cce5130dc1f","c2f0de2ef4753dc0ec8dd2da5ebf8e77f07d2ac0791357a9e3f2537071b33762") DOC_END END_KV_SERIALIZE_MAP() }; @@ -1445,11 +1445,11 @@ namespace currency bool is_spent; uint64_t global_index; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount) DOC_DSCR("The output's amount, 0 for ZC outputs.") DOC_END - KV_SERIALIZE(pub_keys) DOC_DSCR("List of public keys associated with the output.") DOC_END - KV_SERIALIZE(minimum_sigs) DOC_DSCR("Minimum number of signatures required to spend the output, for multisig outputs only.") DOC_END - KV_SERIALIZE(is_spent) DOC_DSCR("Indicates whether the output has been spent.") DOC_END - KV_SERIALIZE(global_index) DOC_DSCR("Global index of the output for this specific amount.") DOC_END + KV_SERIALIZE(amount) DOC_DSCR("The output's amount, 0 for ZC outputs.") DOC_EXMP(9000000000) DOC_END + KV_SERIALIZE(pub_keys) DOC_DSCR("List of public keys associated with the output.") DOC_EXMP_AGGR("7d0c755e7e24a241847176c9a3cf4c970bcd6377018068abe6fe4535b23f5323") DOC_END + KV_SERIALIZE(minimum_sigs) DOC_DSCR("Minimum number of signatures required to spend the output, for multisig outputs only.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(is_spent) DOC_DSCR("Indicates whether the output has been spent.") DOC_EXMP(false) DOC_END + KV_SERIALIZE(global_index) DOC_DSCR("Global index of the output for this specific amount.") DOC_EXMP(0) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1462,11 +1462,11 @@ namespace currency std::vector global_indexes; std::vector etc_options; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount) DOC_DSCR("The amount of coins being transacted.") DOC_END + KV_SERIALIZE(amount) DOC_DSCR("The amount of coins being transacted.") DOC_EXMP(1000000000000) DOC_END KV_SERIALIZE(htlc_origin) DOC_DSCR("Origin hash for HTLC (Hash Time Locked Contract).") DOC_END - KV_SERIALIZE(kimage_or_ms_id) DOC_DSCR("Contains either the key image for the input or the multisig output ID, depending on the input type.") DOC_END - KV_SERIALIZE(global_indexes) DOC_DSCR("List of global indexes indicating the outputs referenced by this input, where only one is actually being spent.") DOC_END - KV_SERIALIZE(multisig_count) DOC_DSCR("Number of multisig signatures used, relevant only for multisig outputs.") DOC_END + KV_SERIALIZE(kimage_or_ms_id) DOC_DSCR("Contains either the key image for the input or the multisig output ID, depending on the input type.") DOC_EXMP("2540e0544b1fed3b104976f803dbd83681335c427f9d601d9d5aecf86ef276d2") DOC_END + KV_SERIALIZE(global_indexes) DOC_DSCR("List of global indexes indicating the outputs referenced by this input, where only one is actually being spent.") DOC_EXMP_AGGR(0,2,12,27) DOC_END + KV_SERIALIZE(multisig_count) DOC_DSCR("Number of multisig signatures used, relevant only for multisig outputs.") DOC_EXMP(0) DOC_END KV_SERIALIZE(etc_options) DOC_DSCR("Auxiliary options associated with the input, containing additional configuration or data.") DOC_END END_KV_SERIALIZE_MAP() }; @@ -1477,9 +1477,9 @@ namespace currency std::string short_view; std::string details_view; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(type) DOC_DSCR("Type of the extra entry in the transaction.") DOC_END - KV_SERIALIZE(short_view) DOC_DSCR("A concise representation of the extra entry.") DOC_END - KV_SERIALIZE(details_view) DOC_DSCR("A detailed representation of the extra entry.") DOC_END + KV_SERIALIZE(type) DOC_DSCR("Type of the extra entry in the transaction.") DOC_EXMP("pub_key") DOC_END + KV_SERIALIZE(short_view) DOC_DSCR("A concise representation of the extra entry.") DOC_EXMP("0feef5e2ea0e88b592c0a0e6639ce73e12ea9b3136d89464748fcb60bb6f18f5") DOC_END + KV_SERIALIZE(details_view) DOC_DSCR("A detailed representation of the extra entry.") DOC_EXMP("") DOC_END END_KV_SERIALIZE_MAP() }; @@ -1501,19 +1501,19 @@ namespace currency std::string object_in_json; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_BLOB_AS_BASE64_STRING(blob) DOC_DSCR("Serialized form of the transaction, encoded in Base64.") DOC_END - KV_SERIALIZE(blob_size) DOC_DSCR("Size of the serialized transaction in bytes.") DOC_END - KV_SERIALIZE(timestamp) DOC_DSCR("Timestamp when the transaction was created.") DOC_END - KV_SERIALIZE(keeper_block) DOC_DSCR("Block height where the transaction is confirmed, or -1 if it is unconfirmed.") DOC_END - KV_SERIALIZE(fee) DOC_DSCR("Transaction fee in the smallest currency unit.") DOC_END - KV_SERIALIZE(amount) DOC_DSCR("Total output amount of the transaction (legacy, for pre-Zarcanum txs).") DOC_END - KV_SERIALIZE(id) DOC_DSCR("Hash of the transaction.") DOC_END - KV_SERIALIZE(pub_key) DOC_DSCR("Public key associated with the transaction.") DOC_END - KV_SERIALIZE(outs) DOC_DSCR("Outputs of the transaction.") DOC_END - KV_SERIALIZE(ins) DOC_DSCR("Inputs of the transaction.") DOC_END - KV_SERIALIZE(extra) DOC_DSCR("Extra data associated with the transaction.") DOC_END - KV_SERIALIZE(attachments) DOC_DSCR("Additional attachments to the transaction.") DOC_END - KV_SERIALIZE_BLOB_AS_BASE64_STRING(object_in_json) DOC_DSCR("Serialized transaction represented in JSON, encoded in Base64.") DOC_END + KV_SERIALIZE_BLOB_AS_BASE64_STRING(blob) DOC_DSCR("Serialized form of the transaction, encoded in Base64.") DOC_EXMP("ARMBgKCUpY0dBBoAAAAAAAAAABoCAAAAAAAAABoKAAAAAAAAABoPAAAAAAAAACVA4FRLH") DOC_END + KV_SERIALIZE(blob_size) DOC_DSCR("Size of the serialized transaction in bytes.") DOC_EXMP(6794) DOC_END + KV_SERIALIZE(timestamp) DOC_DSCR("Timestamp when the transaction was created.") DOC_EXMP(1557345925) DOC_END + KV_SERIALIZE(keeper_block) DOC_DSCR("Block height where the transaction is confirmed, or -1 if it is unconfirmed.") DOC_EXMP(51) DOC_END + KV_SERIALIZE(fee) DOC_DSCR("Transaction fee in the smallest currency unit.") DOC_EXMP(1000000000) DOC_END + KV_SERIALIZE(amount) DOC_DSCR("Total output amount of the transaction (legacy, for pre-Zarcanum txs).") DOC_EXMP(18999000000000) DOC_END + KV_SERIALIZE(id) DOC_DSCR("Hash of the transaction.") DOC_EXMP("a6e8da986858e6825fce7a192097e6afae4e889cabe853a9c29b964985b23da8") DOC_END + KV_SERIALIZE(pub_key) DOC_DSCR("Public key associated with the transaction.") DOC_EXMP("0feef5e2ea0e88b592c0a0e6639ce73e12ea9b3136d89464748fcb60bb6f18f5") DOC_END + KV_SERIALIZE(outs) DOC_DSCR("Outputs of the transaction.") DOC_EXMP_AUTO(1) DOC_END + KV_SERIALIZE(ins) DOC_DSCR("Inputs of the transaction.") DOC_EXMP_AUTO(1) DOC_END + KV_SERIALIZE(extra) DOC_DSCR("Extra data associated with the transaction.") DOC_EXMP_AUTO(1) DOC_END + KV_SERIALIZE(attachments) DOC_DSCR("Additional attachments to the transaction.") DOC_EXMP_AUTO(1) DOC_END + KV_SERIALIZE_BLOB_AS_BASE64_STRING(object_in_json) DOC_DSCR("Serialized transaction represented in JSON, encoded in Base64.") DOC_EXMP("ewogICJ2ZXJzaW9uIjogMSwgCiAgInZpbiI6IFsgewogICAgIC") DOC_END END_KV_SERIALIZE_MAP() }; @@ -1525,10 +1525,10 @@ namespace currency uint64_t sz; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(id) DOC_DSCR("Hash of the transaction.") DOC_END - KV_SERIALIZE(fee) DOC_DSCR("Transaction fee in the smallest currency unit.") DOC_END - KV_SERIALIZE(total_amount) DOC_DSCR("Total amount transferred in the transaction (legacy, for pre-Zarcanum txs).") DOC_END - KV_SERIALIZE(sz) DOC_DSCR("Size of the transaction in bytes.") DOC_END + KV_SERIALIZE(id) DOC_DSCR("Hash of the transaction.") DOC_EXMP("a6e8da986858e6825fce7a192097e6afae4e889cabe853a9c29b964985b23da8") DOC_END + KV_SERIALIZE(fee) DOC_DSCR("Transaction fee in the smallest currency unit.") DOC_EXMP(1000000000) DOC_END + KV_SERIALIZE(total_amount) DOC_DSCR("Total amount transferred in the transaction (legacy, for pre-Zarcanum txs).") DOC_EXMP(9000000000) DOC_END + KV_SERIALIZE(sz) DOC_DSCR("Size of the transaction in bytes.") DOC_EXMP(6142) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1561,30 +1561,30 @@ namespace currency std::string object_in_json; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(blob) DOC_DSCR("Serialized form of the block.") DOC_END - KV_SERIALIZE(height) DOC_DSCR("Height of the block in the blockchain.") DOC_END - KV_SERIALIZE(timestamp) DOC_DSCR("Timestamp when the block was created, in PoS blocks used for mining.") DOC_END - KV_SERIALIZE(actual_timestamp) DOC_DSCR("Actual timestamp encoded in the block's extra data for PoS blocks.") DOC_END - KV_SERIALIZE(block_cumulative_size) DOC_DSCR("Cumulative size of the block including all transactions.") DOC_END - KV_SERIALIZE(total_txs_size) DOC_DSCR("Total size of all transactions included in the block.") DOC_END + KV_SERIALIZE(blob) DOC_DSCR("Serialized form of the block.") DOC_EXMP("") DOC_END + KV_SERIALIZE(height) DOC_DSCR("Height of the block in the blockchain.") DOC_EXMP(51) DOC_END + KV_SERIALIZE(timestamp) DOC_DSCR("Timestamp when the block was created, in PoS blocks used for mining.") DOC_EXMP(1557345925) DOC_END + KV_SERIALIZE(actual_timestamp) DOC_DSCR("Actual timestamp encoded in the block's extra data for PoS blocks.") DOC_EXMP(1557345925) DOC_END + KV_SERIALIZE(block_cumulative_size) DOC_DSCR("Cumulative size of the block including all transactions.") DOC_EXMP(6794) DOC_END + KV_SERIALIZE(total_txs_size) DOC_DSCR("Total size of all transactions included in the block.") DOC_EXMP(6794) DOC_END KV_SERIALIZE(block_tself_size) // TODO ? - KV_SERIALIZE(base_reward) DOC_DSCR("Base mining reward for the block.") DOC_END - KV_SERIALIZE(summary_reward) DOC_DSCR("Total reward for the block, including base reward and transaction fees (legacy).") DOC_END - KV_SERIALIZE(total_fee) DOC_DSCR("Total transaction fees included in the block.") DOC_END - KV_SERIALIZE(penalty) DOC_DSCR("Penalty applied to the reward if the block is larger than median but not large enough to be rejected.") DOC_END - KV_SERIALIZE(id) DOC_DSCR("Unique identifier of the block.") DOC_END - KV_SERIALIZE(prev_id) DOC_DSCR("Hash of the previous block in the chain.") DOC_END + KV_SERIALIZE(base_reward) DOC_DSCR("Base mining reward for the block.") DOC_EXMP(1000000000000) DOC_END + KV_SERIALIZE(summary_reward) DOC_DSCR("Total reward for the block, including base reward and transaction fees (legacy).") DOC_EXMP(1001000000000) DOC_END + KV_SERIALIZE(total_fee) DOC_DSCR("Total transaction fees included in the block.") DOC_EXMP(1000000000) DOC_END + KV_SERIALIZE(penalty) DOC_DSCR("Penalty applied to the reward if the block is larger than median but not large enough to be rejected.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(id) DOC_DSCR("Unique identifier of the block.") DOC_EXMP("af05b814c75e10872afc0345108e830884bc4c32091db783505abe3dac9929cf") DOC_END + KV_SERIALIZE(prev_id) DOC_DSCR("Hash of the previous block in the chain.") DOC_EXMP("37fe382c755bb8869e4f5255f2aed6a8fb503e195bb4180b65b8e1450b84cafe") DOC_END KV_SERIALIZE(pow_seed) // TODO - KV_SERIALIZE(cumulative_diff_adjusted) DOC_DSCR("Adjusted cumulative difficulty of the blockchain up to this block.") DOC_END - KV_SERIALIZE(cumulative_diff_precise) DOC_DSCR("Precise cumulative difficulty of the blockchain up to this block.") DOC_END - KV_SERIALIZE(difficulty) DOC_DSCR("Mining difficulty of the block.") DOC_END - KV_SERIALIZE(already_generated_coins) DOC_DSCR("Total amount of coins generated in the blockchain up to this block.") DOC_END - KV_SERIALIZE(this_block_fee_median) DOC_DSCR("Median transaction fee of the transactions within this block.") DOC_END + KV_SERIALIZE(cumulative_diff_adjusted) DOC_DSCR("Adjusted cumulative difficulty of the blockchain up to this block.") DOC_EXMP("42413051198") DOC_END + KV_SERIALIZE(cumulative_diff_precise) DOC_DSCR("Precise cumulative difficulty of the blockchain up to this block.") DOC_EXMP("28881828324942") DOC_END + KV_SERIALIZE(difficulty) DOC_DSCR("Mining difficulty of the block.") DOC_EXMP("951296929031") DOC_END + KV_SERIALIZE(already_generated_coins) DOC_DSCR("Total amount of coins generated in the blockchain up to this block.") DOC_EXMP("17517253670000000000") DOC_END + KV_SERIALIZE(this_block_fee_median) DOC_DSCR("Median transaction fee of the transactions within this block.") DOC_EXMP(1000000000) DOC_END KV_SERIALIZE(effective_fee_median) // TODO KV_SERIALIZE(transactions_details) DOC_DSCR("Detailed information about each transaction included in the block.") DOC_EXMP_AUTO(1) DOC_END - KV_SERIALIZE(type) DOC_DSCR("Type of the block.") DOC_END - KV_SERIALIZE(is_orphan) DOC_DSCR("Indicates whether the block is an orphan.") DOC_END - KV_SERIALIZE(miner_text_info) DOC_DSCR("Additional textual information provided by the miner of the block.") DOC_END + KV_SERIALIZE(type) DOC_DSCR("Type of the block.") DOC_EXMP(1) DOC_END + KV_SERIALIZE(is_orphan) DOC_DSCR("Indicates whether the block is an orphan.") DOC_EXMP(false) DOC_END + KV_SERIALIZE(miner_text_info) DOC_DSCR("Additional textual information provided by the miner of the block.") DOC_EXMP("") DOC_END KV_SERIALIZE(object_in_json) DOC_DSCR("Serialized representation of the block in JSON format.") DOC_END END_KV_SERIALIZE_MAP() }; @@ -1603,8 +1603,8 @@ namespace currency bool ignore_transactions; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(height_start) DOC_DSCR("The starting block height from which block details are retrieved.") DOC_END - KV_SERIALIZE(count) DOC_DSCR("The number of blocks to retrieve from the starting height.") DOC_END + KV_SERIALIZE(height_start) DOC_DSCR("The starting block height from which block details are retrieved.") DOC_EXMP(51) DOC_END + KV_SERIALIZE(count) DOC_DSCR("The number of blocks to retrieve from the starting height.") DOC_EXMP(1) DOC_END KV_SERIALIZE(ignore_transactions) // TODO END_KV_SERIALIZE_MAP() }; @@ -1633,8 +1633,8 @@ namespace currency uint64_t count; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(offset) DOC_DSCR("The offset in the list of alternative blocks from which to start retrieval.") DOC_END - KV_SERIALIZE(count) DOC_DSCR("The number of alternative blocks to retrieve from the specified offset.") DOC_END + KV_SERIALIZE(offset) DOC_DSCR("The offset in the list of alternative blocks from which to start retrieval.") DOC_EXMP(0) DOC_END + KV_SERIALIZE(count) DOC_DSCR("The number of alternative blocks to retrieve from the specified offset.") DOC_EXMP(1) DOC_END END_KV_SERIALIZE_MAP() }; @@ -1661,7 +1661,7 @@ namespace currency crypto::hash id; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_POD_AS_HEX_STRING(id) DOC_DSCR("The hash ID of the block for which detailed information is being requested.") DOC_END + KV_SERIALIZE_POD_AS_HEX_STRING(id) DOC_DSCR("The hash ID of the block for which detailed information is being requested.") DOC_EXMP("4cf2c7c7e16d1a2a0771cd552c696dd94e7db4e1031982ed88eff99d5006ee4a") DOC_END END_KV_SERIALIZE_MAP() }; @@ -1688,7 +1688,7 @@ namespace currency std::list ids; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(ids) DOC_DSCR("List of transaction IDs.") DOC_END + KV_SERIALIZE(ids) DOC_DSCR("List of transaction IDs.") DOC_EXMP_AGGR("bd9a89f95c9115d29540c6778dab9d9798eb251143dcd4b8960fcd9730a1471c","1c938f04c935d976310c4338fc570ea20777951471609f3edecb341ea4932b0a") DOC_END END_KV_SERIALIZE_MAP() }; @@ -1699,7 +1699,7 @@ namespace currency BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END - KV_SERIALIZE(txs) DOC_DSCR("List of transactions with detailed information.") DOC_END + KV_SERIALIZE(txs) DOC_DSCR("List of transactions with detailed information.") DOC_EXMP_AUTO(1) DOC_END END_KV_SERIALIZE_MAP() }; }; @@ -1715,7 +1715,7 @@ namespace currency std::list ids; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(ids) DOC_DSCR("List of transaction IDs.") DOC_END + KV_SERIALIZE(ids) DOC_DSCR("List of transaction IDs.") DOC_EXMP_AGGR("bd9a89f95c9115d29540c6778dab9d9798eb251143dcd4b8960fcd9730a1471c","1c938f04c935d976310c4338fc570ea20777951471609f3edecb341ea4932b0a") DOC_END END_KV_SERIALIZE_MAP() }; @@ -1726,7 +1726,7 @@ namespace currency BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END - KV_SERIALIZE(txs) DOC_DSCR("List of transactions with detailed information.") DOC_END + KV_SERIALIZE(txs) DOC_DSCR("List of transactions with detailed information.") DOC_EXMP_AUTO(1) DOC_END END_KV_SERIALIZE_MAP() }; }; @@ -1750,7 +1750,7 @@ namespace currency BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END - KV_SERIALIZE(ids) DOC_DSCR("List of all transaction IDs currently in the transaction pool.") DOC_END + KV_SERIALIZE(ids) DOC_DSCR("List of all transaction IDs currently in the transaction pool.") DOC_EXMP_AUTO(1) DOC_END END_KV_SERIALIZE_MAP() }; }; @@ -1796,7 +1796,7 @@ namespace currency std::string tx_hash; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tx_hash) DOC_DSCR("The hash of the transaction for which detailed information is being requested.") DOC_END + KV_SERIALIZE(tx_hash) DOC_DSCR("The hash of the transaction for which detailed information is being requested.") DOC_EXMP("d46c415c3aa3f3e17bd0bf85ffb813cacf4d9595d2d5392f42dacbaffcffdc70") DOC_END END_KV_SERIALIZE_MAP() }; @@ -1807,7 +1807,7 @@ namespace currency BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END - KV_SERIALIZE(tx_info) DOC_DSCR("Detailed information about the transaction.") DOC_END + KV_SERIALIZE(tx_info) DOC_DSCR("Detailed information about the transaction.") DOC_EXMP_AUTO() DOC_END END_KV_SERIALIZE_MAP() }; }; @@ -1828,7 +1828,7 @@ namespace currency std::string id; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(id) DOC_DSCR("The identifier used to search across various types of entities.") DOC_END + KV_SERIALIZE(id) DOC_DSCR("The identifier used to search across various types of entities.") DOC_EXMP("729811f9340537e8d5641949e6cc58261f91f109687a706f39bae9514757e819") DOC_END END_KV_SERIALIZE_MAP() }; @@ -1839,7 +1839,7 @@ namespace currency BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END - KV_SERIALIZE(types_found) DOC_DSCR("List of entity types where the identifier was found.") DOC_END + KV_SERIALIZE(types_found) DOC_DSCR("List of entity types where the identifier was found.") DOC_EXMP_AGGR("key_image") DOC_END END_KV_SERIALIZE_MAP() }; }; @@ -1891,7 +1891,7 @@ namespace currency BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) DOC_DSCR("Status of the call.") DOC_EXMP(API_RETURN_CODE_OK) DOC_END - KV_SERIALIZE(expiration_median) DOC_DSCR("The median timestamp from the last N blocks, used to determine if transactions are expired based on their timestamp.") DOC_END + KV_SERIALIZE(expiration_median) DOC_DSCR("The median timestamp from the last N blocks, used to determine if transactions are expired based on their timestamp.") DOC_EXMP(1719591540) DOC_END END_KV_SERIALIZE_MAP() }; }; @@ -1910,10 +1910,10 @@ namespace currency std::string alias; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(buff) DOC_DSCR("Base64 encoded data for which the signature is to be validated.") DOC_END - KV_SERIALIZE_POD_AS_HEX_STRING(sig) DOC_DSCR("Schnorr signature to validate, encoded as a hexadecimal string.") DOC_END + KV_SERIALIZE(buff) DOC_DSCR("Base64 encoded data for which the signature is to be validated.") DOC_EXMP("SSBkaWRuJ3QgZXhwZWN0IGFueW9uZSB0byBkZWNyeXB0IHRoaXMgZGF0YSwgc2luY2UgaXQncyBqdXN0IGFuIGV4YW1wbGUuIEJ1dCB5b3UgZGVjcnlwdGVkIGl0ISBJJ20gYW1hemVkLg==") DOC_END + KV_SERIALIZE_POD_AS_HEX_STRING(sig) DOC_DSCR("Schnorr signature to validate, encoded as a hexadecimal string.") DOC_EXMP("5c202d4bf82c2dd3c6354e2f02826ca72c797950dbe8db5bc5e3b2e60290a407ac2ef85bfc905ace8fe3b3819217084c00faf7237fee3ad2f6a7f662636cd20f") DOC_END KV_SERIALIZE_POD_AS_HEX_STRING(pkey) DOC_DSCR("Public key used for signature verification, encoded as a hexadecimal string. If null or not set, the public key is retrieved using the provided alias.") DOC_END - KV_SERIALIZE(alias) DOC_DSCR("Alias to retrieve the associated public spend key if no explicit public key is provided for verification.") DOC_END + KV_SERIALIZE(alias) DOC_DSCR("Alias to retrieve the associated public spend key if no explicit public key is provided for verification.") DOC_EXMP("sowle") DOC_END END_KV_SERIALIZE_MAP() }; From 0e69e059fe106d05ee4978a8ee3a6142ce103676 Mon Sep 17 00:00:00 2001 From: sowle Date: Sat, 29 Jun 2024 13:59:01 +0200 Subject: [PATCH 40/53] fixed incorrect end-of-object indentation in dump_as_json() and similar functions --- contrib/epee/include/storages/portable_storage_to_json.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/epee/include/storages/portable_storage_to_json.h b/contrib/epee/include/storages/portable_storage_to_json.h index 3292c952..7230a14b 100644 --- a/contrib/epee/include/storages/portable_storage_to_json.h +++ b/contrib/epee/include/storages/portable_storage_to_json.h @@ -116,7 +116,7 @@ namespace epee template static void handle_obj_end(t_stream& strm, size_t indent) { - strm << "}"; + strm << make_indent(indent) << "}"; } template From fb22df48503dc4fdfeeb856ff3f0c1f7f473677d Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 2 Jul 2024 17:18:47 +0200 Subject: [PATCH 41/53] build: unused mdbx tools projects are excluded from the default MSVC build for convenience --- contrib/db/CMakeLists.txt | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/contrib/db/CMakeLists.txt b/contrib/db/CMakeLists.txt index 6f2213b4..c558ad63 100644 --- a/contrib/db/CMakeLists.txt +++ b/contrib/db/CMakeLists.txt @@ -6,15 +6,18 @@ if(CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android") endif() - message("DB ENGINE: lmdb") - add_subdirectory(liblmdb) - if(MSVC) - target_compile_options(lmdb PRIVATE /wd4996 /wd4503 /wd4345 /wd4267 /wd4244 /wd4146 /wd4333 /wd4172) - else() - # Warnings as used by LMDB itself (LMDB_0.9.23) - target_compile_options(lmdb PRIVATE -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized) - endif() - if(NOT DISABLE_MDBX) - message("DB ENGINE: mdbx") - add_subdirectory(libmdbx) - endif() +message("DB ENGINE: lmdb") +add_subdirectory(liblmdb) +if(MSVC) + target_compile_options(lmdb PRIVATE /wd4996 /wd4503 /wd4345 /wd4267 /wd4244 /wd4146 /wd4333 /wd4172) +else() + # Warnings as used by LMDB itself (LMDB_0.9.23) + target_compile_options(lmdb PRIVATE -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized) +endif() + +if(NOT DISABLE_MDBX) + message("DB ENGINE: mdbx") + add_subdirectory(libmdbx) + # remove mdbx tools from the default MSVC build + set_target_properties(mdbx_chk mdbx_copy mdbx_dump mdbx_load mdbx_stat PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1) +endif() From 2b9caf2cb3394b6d33293bf25bdb1c69349cf43f Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 2 Jul 2024 17:20:02 +0200 Subject: [PATCH 42/53] docs: some asset_descriptor fileds clarified a bit --- src/currency_core/currency_basic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h index 80ddef17..771ae1a8 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -733,12 +733,12 @@ namespace currency BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(total_max_supply) DOC_DSCR("Maximum possible supply for given asset, can't be changed after deployment") DOC_EXMP(1000000000000000000) DOC_END - KV_SERIALIZE(current_supply) DOC_DSCR("Currently emitted supply for given asset") DOC_EXMP(500000000000000000) DOC_END + KV_SERIALIZE(current_supply) DOC_DSCR("Currently emitted supply for given asset (ignored for REGISTER operation)") DOC_EXMP(500000000000000000) DOC_END KV_SERIALIZE(decimal_point) DOC_DSCR("Decimal point") DOC_EXMP(12) DOC_END KV_SERIALIZE(ticker) DOC_DSCR("Ticker associated with asset") DOC_EXMP("ZUSD") DOC_END KV_SERIALIZE(full_name) DOC_DSCR("Full name of the asset") DOC_EXMP("Zano wrapped USD") DOC_END KV_SERIALIZE(meta_info) DOC_DSCR("Any other information assetiaded with asset in a free form") DOC_EXMP("Stable and private") DOC_END - KV_SERIALIZE_POD_AS_HEX_STRING(owner) DOC_DSCR("Owner's key, used to validate any operations on the asset altering, could be changed in case of transfer ownership") DOC_EXMP("f74bb56a5b4fa562e679ccaadd697463498a66de4f1760b2cd40f11c3a00a7a8") DOC_END + KV_SERIALIZE_POD_AS_HEX_STRING(owner) DOC_DSCR("Owner's key, used only for EMIT and UPDATE validation, could be changed by transferring asset ownership") DOC_EXMP("f74bb56a5b4fa562e679ccaadd697463498a66de4f1760b2cd40f11c3a00a7a8") DOC_END KV_SERIALIZE(hidden_supply) DOC_DSCR("This one reserved for future use, will be documented later") DOC_END END_KV_SERIALIZE_MAP() }; From 9150c316667f4de2346bb1498d4a7b8189a078cc Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 2 Jul 2024 17:22:07 +0200 Subject: [PATCH 43/53] fixed wallet2::finalize_transaction() to correctly handle too big txs (and not to pass them to the daemon) --- src/wallet/wallet2.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 16aabd4e..e68e4657 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -7605,7 +7605,8 @@ void wallet2::finalize_transaction(currency::finalize_tx_param& ftp, currency::f } //TIME_MEASURE_FINISH_MS(sign_ms_input_time); - THROW_IF_FALSE_WALLET_EX(get_object_blobsize(result.tx) < CURRENCY_MAX_TRANSACTION_BLOB_SIZE, error::tx_too_big, result.tx, m_upper_transaction_size_limit); + size_t tx_blob_size = tx_to_blob(result.tx).size(); + THROW_IF_FALSE_WALLET_EX(tx_blob_size < CURRENCY_MAX_TRANSACTION_BLOB_SIZE, error::tx_too_big, result.tx, m_upper_transaction_size_limit); if (store_tx_secret_key) m_tx_keys.insert(std::make_pair(get_transaction_hash(result.tx), result.one_time_key)); From b6e84b460e0b9493083dcedfde9212fdeef56ea5 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 2 Jul 2024 20:49:51 +0200 Subject: [PATCH 44/53] added decimal point support to currency::parse_amount() + minor refactoring --- src/currency_core/currency_format_utils.cpp | 11 +- src/currency_core/currency_format_utils.h | 2 +- src/simplewallet/simplewallet.cpp | 4 +- src/wallet/wallets_manager.cpp | 2 +- tests/unit_tests/amounts_tests.cpp | 117 +++++++++++++++++++- tests/unit_tests/test_format_utils.cpp | 45 -------- 6 files changed, 121 insertions(+), 60 deletions(-) diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 2c8e5c2a..ce80baf3 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -793,8 +793,7 @@ namespace currency } } //--------------------------------------------------------------- - // TODO: reverse order of arguments - bool parse_amount(uint64_t& amount, const std::string& str_amount_) + bool parse_amount(const std::string& str_amount_, uint64_t& amount, const size_t decimal_point /* = CURRENCY_DISPLAY_DECIMAL_POINT */) { std::string str_amount = str_amount_; boost::algorithm::trim(str_amount); @@ -804,12 +803,12 @@ namespace currency if (std::string::npos != point_index) { fraction_size = str_amount.size() - point_index - 1; - while (CURRENCY_DISPLAY_DECIMAL_POINT < fraction_size && '0' == str_amount.back()) + while (decimal_point < fraction_size && '0' == str_amount.back()) { str_amount.erase(str_amount.size() - 1, 1); --fraction_size; } - if (CURRENCY_DISPLAY_DECIMAL_POINT < fraction_size) + if (decimal_point < fraction_size) return false; str_amount.erase(point_index, 1); } @@ -821,9 +820,9 @@ namespace currency if (str_amount.empty()) return false; - if (fraction_size < CURRENCY_DISPLAY_DECIMAL_POINT) + if (fraction_size < decimal_point) { - str_amount.append(CURRENCY_DISPLAY_DECIMAL_POINT - fraction_size, '0'); + str_amount.append(decimal_point - fraction_size, '0'); } return string_tools::get_xtype_from_string(amount, str_amount); diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index 5c4ea929..66fcce6a 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -402,7 +402,7 @@ namespace currency uint64_t get_outs_money_amount(const transaction& tx, const currency::account_keys& acc_keys_for_hidden_amounts = currency::null_acc_keys); bool check_inputs_types_supported(const transaction& tx); bool check_outs_valid(const transaction& tx); - bool parse_amount(uint64_t& amount, const std::string& str_amount); + bool parse_amount(const std::string& str_amount, uint64_t& amount, const size_t decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT); bool parse_tracking_seed(const std::string& tracking_seed, account_public_address& address, crypto::secret_key& view_sec_key, uint64_t& creation_timestamp); diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 3935cb4c..ca67420c 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2592,7 +2592,7 @@ bool simple_wallet::sweep_below(const std::vector &args) } uint64_t amount = 0; - r = currency::parse_amount(amount, args[2]); + r = currency::parse_amount(args[2], amount); if (!r || amount == 0) { fail_msg_writer() << "incorrect amount: " << args[2]; @@ -3127,7 +3127,7 @@ int main(int argc, char* argv[]) uint64_t max_amount = 0; CHECK_AND_ASSERT_MES(epee::string_tools::string_to_num_fast(params[0], outs_min) && outs_min > 0 && outs_min < 256, EXIT_FAILURE, "incorrect param: " << params[0]); CHECK_AND_ASSERT_MES(epee::string_tools::string_to_num_fast(params[1], outs_max) && outs_max > 0 && outs_max < 256, EXIT_FAILURE, "incorrect param: " << params[1]); - CHECK_AND_ASSERT_MES(currency::parse_amount(max_amount, params[2]), EXIT_FAILURE, "incorrect param: " << params[2]); + CHECK_AND_ASSERT_MES(currency::parse_amount(params[2], max_amount), EXIT_FAILURE, "incorrect param: " << params[2]); wal.set_defragmentation_tx_settings(true, outs_min, outs_max, max_amount); } } diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index b039e86a..7f3ee253 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -1539,7 +1539,7 @@ std::string wallets_manager::transfer(uint64_t wallet_id, const view::transfer_p } - if(!currency::parse_amount(dsts.back().amount, d.amount)) + if(!currency::parse_amount(d.amount, dsts.back().amount)) { return API_RETURN_CODE_BAD_ARG_WRONG_AMOUNT; } diff --git a/tests/unit_tests/amounts_tests.cpp b/tests/unit_tests/amounts_tests.cpp index 300b92a7..24aa5b84 100644 --- a/tests/unit_tests/amounts_tests.cpp +++ b/tests/unit_tests/amounts_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022 Zano Project +// Copyright (c) 2022-2024 Zano Project // Copyright (c) 2012-2013 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -10,23 +10,23 @@ using namespace currency; namespace { - void do_pos_test(uint64_t expected, const std::string& str) + void do_pos_test(uint64_t expected, const std::string& str, size_t decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT) { uint64_t val; std::string number_str = str; std::replace(number_str.begin(), number_str.end(), '_', '.'); number_str.erase(std::remove(number_str.begin(), number_str.end(), '~'), number_str.end()); - ASSERT_TRUE(parse_amount(val, number_str)); + ASSERT_TRUE(parse_amount(number_str, val, decimal_point)); ASSERT_EQ(expected, val); } - void do_neg_test(const std::string& str) + void do_neg_test(const std::string& str, size_t decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT) { uint64_t val; std::string number_str = str; std::replace(number_str.begin(), number_str.end(), '_', '.'); number_str.erase(std::remove(number_str.begin(), number_str.end(), '~'), number_str.end()); - ASSERT_FALSE(parse_amount(val, number_str)); + ASSERT_FALSE(parse_amount(number_str, val, decimal_point)); } } @@ -48,6 +48,23 @@ namespace do_neg_test(#str); \ } +#define TEST_pos_dp(expected, str, decimal_point) \ + TEST(parse_amount, handles_pos_ ## str ## _dp ## decimal_point) \ + { \ + do_pos_test(UINT64_C(expected), #str, decimal_point); \ + } + +#define TEST_neg_dp(str, decimal_point) \ + TEST(parse_amount, handles_neg_ ## str ## _dp ## decimal_point) \ + { \ + do_neg_test(#str, decimal_point); \ + } + +#define TEST_neg_n_dp(str, name, decimal_point) \ + TEST(parse_amount, handles_neg_ ## name ## _dp ## decimal_point) \ + { \ + do_neg_test(#str, decimal_point); \ + } TEST_pos(0, 0); TEST_pos(0, 00); @@ -96,6 +113,44 @@ TEST_pos(18446744073700000000, 18446744_0737000000000); TEST_pos(18446744073700000000, 18446744_07370000000000000000000); TEST_pos(18446744073709551615, 18446744_073709551615); +// non-standard decimal point +TEST_pos_dp(0, 0_0, 3); +TEST_pos_dp(0, 00_0, 3); +TEST_pos_dp(0, 00_00, 3); +TEST_pos_dp(0, 00000000_00, 3); +TEST_pos_dp(0, 00_000000000, 3); +TEST_pos_dp(0, 00_00000000000000000000000000000000, 3); + +TEST_pos_dp( 65535, 65535, 0); +TEST_pos_dp( 6553500, 65535, 2); +TEST_pos_dp( 65535000000, 65535, 6); +TEST_pos_dp( 18000000000000000000, 18, 18); +TEST_pos_dp( 1, 0_1, 1); +TEST_pos_dp( 10, 0_1, 2); +TEST_pos_dp( 100, 0_1, 3); +TEST_pos_dp( 10000000000000000000, 0_1, 20); +TEST_pos_dp( 1, 0_001, 3); +TEST_pos_dp( 123, 0_123, 3); +TEST_pos_dp( 1230, 0_123, 4); +TEST_pos_dp( 12300, 0_123, 5); +TEST_pos_dp( 123000, 0_123, 6); + +TEST_pos_dp(18446744073709551615, 18446744073709551615, 0); +TEST_pos_dp(18446744073709551615, 18446744073709551615_0, 0); + +TEST_pos_dp(18446744073709551615, 1844674407370955161_5, 1); +TEST_pos_dp(18446744073709551615, 1844674407370955161_50, 1); + +TEST_pos_dp(18446744073709551615, 18446744073709551_615, 3); +TEST_pos_dp(18446744073709551615, 18446744073709551_615000, 3); + +TEST_pos_dp(18446744073709551615, 1_8446744073709551615, 19); +TEST_pos_dp(18446744073709551615, 1_844674407370955161500, 19); + +TEST_pos_dp(18446744073709551615, 0_18446744073709551615, 20); +TEST_pos_dp(18446744073709551615, 0_1844674407370955161500, 20); + + // Invalid numbers TEST_neg_n(~, empty_string); TEST_neg_n(-0, minus_0); @@ -109,10 +164,17 @@ TEST_neg(0_0000000000001); TEST_neg(0_0000000000009); TEST_neg(18446744_0737000000001); +TEST_neg_dp(00_184467440737095516150001, 20); +TEST_neg_dp(00_184467440737095516151, 20); +TEST_neg_dp(1_2, 0); + // Overflow TEST_neg(184467440737_09551616); TEST_neg(184467440738); TEST_neg(18446744073709551616); +TEST_neg_dp(18446744073709551616, 0); +TEST_neg_dp(1844674407370955161_60, 1); +TEST_neg_dp(0_18446744073709551616, 20); // Two or more points TEST_neg(__); @@ -123,6 +185,51 @@ TEST_neg(0_0_); TEST_neg(_0_0); TEST_neg(0_0_0); +// moved from test_format_utils.cpp +TEST(validate_parse_amount_case, validate_parse_amount) +{ + uint64_t res = 0; + bool r = currency::parse_amount("0.0001", res); + ASSERT_TRUE(r); + ASSERT_EQ(res, 100000000); + + r = currency::parse_amount("100.0001", res); + ASSERT_TRUE(r); + ASSERT_EQ(res, 100000100000000); + + r = currency::parse_amount("000.0000", res); + ASSERT_TRUE(r); + ASSERT_EQ(res, 0); + + r = currency::parse_amount("0", res); + ASSERT_TRUE(r); + ASSERT_EQ(res, 0); + + + r = currency::parse_amount(" 100.0001 ", res); + ASSERT_TRUE(r); + ASSERT_EQ(res, 100000100000000); + + r = currency::parse_amount(" 100.0000 ", res); + ASSERT_TRUE(r); + ASSERT_EQ(res, 100000000000000); + + r = currency::parse_amount(" 100. 0000 ", res); + ASSERT_FALSE(r); + + r = currency::parse_amount("100. 0000", res); + ASSERT_FALSE(r); + + r = currency::parse_amount("100 . 0000", res); + ASSERT_FALSE(r); + + r = currency::parse_amount("100.00 00", res); + ASSERT_FALSE(r); + + r = currency::parse_amount("1 00.00 00", res); + ASSERT_FALSE(r); +} + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// diff --git a/tests/unit_tests/test_format_utils.cpp b/tests/unit_tests/test_format_utils.cpp index 0e277222..f12c149f 100644 --- a/tests/unit_tests/test_format_utils.cpp +++ b/tests/unit_tests/test_format_utils.cpp @@ -125,48 +125,3 @@ void force_random(forced_to_pod_t& o) // } // // } - - -TEST(validate_parse_amount_case, validate_parse_amount) -{ - uint64_t res = 0; - bool r = currency::parse_amount(res, "0.0001"); - ASSERT_TRUE(r); - ASSERT_EQ(res, 100000000); - - r = currency::parse_amount(res, "100.0001"); - ASSERT_TRUE(r); - ASSERT_EQ(res, 100000100000000); - - r = currency::parse_amount(res, "000.0000"); - ASSERT_TRUE(r); - ASSERT_EQ(res, 0); - - r = currency::parse_amount(res, "0"); - ASSERT_TRUE(r); - ASSERT_EQ(res, 0); - - - r = currency::parse_amount(res, " 100.0001 "); - ASSERT_TRUE(r); - ASSERT_EQ(res, 100000100000000); - - r = currency::parse_amount(res, " 100.0000 "); - ASSERT_TRUE(r); - ASSERT_EQ(res, 100000000000000); - - r = currency::parse_amount(res, " 100. 0000 "); - ASSERT_FALSE(r); - - r = currency::parse_amount(res, "100. 0000"); - ASSERT_FALSE(r); - - r = currency::parse_amount(res, "100 . 0000"); - ASSERT_FALSE(r); - - r = currency::parse_amount(res, "100.00 00"); - ASSERT_FALSE(r); - - r = currency::parse_amount(res, "1 00.00 00"); - ASSERT_FALSE(r); -} From 3a3aed7469f67b66ba98afd74045b6806ebddb68 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 2 Jul 2024 20:51:47 +0200 Subject: [PATCH 45/53] simplewallet: fixed a bug with incorrect parsing of transfer amounts when the decimal point is non-standard + more verbose error messages --- src/simplewallet/simplewallet.cpp | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index ca67420c..14f74dec 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1577,7 +1577,10 @@ bool preprocess_asset_id(std::string& address_arg, crypto::public_key& asset_id) { auto p = address_arg.find(':'); if (p == std::string::npos) + { + asset_id = currency::native_coin_asset_id; return true; + } std::string asset_id_str = address_arg.substr(0, p); std::string address_itself = address_arg.substr(p+1, address_arg.size()); if (!epee::string_tools::parse_tpod_from_hex_string(asset_id_str, asset_id)) @@ -1636,19 +1639,28 @@ bool simple_wallet::transfer(const std::vector &args_) currency::tx_destination_entry de = AUTO_VAL_INIT(de); de.addr.resize(1); - bool ok = currency::parse_amount(de.amount, local_args[i + 1]); - if (!ok || 0 == de.amount) - { - fail_msg_writer() << "amount is wrong: " << local_args[i] << ' ' << local_args[i + 1] << - ", expected number from 0 to " << print_money(std::numeric_limits::max()); - return true; - } - if (!preprocess_asset_id(local_args[i], de.asset_id)) { fail_msg_writer() << "address is wrong: " << local_args[i]; return true; } + + uint32_t asset_flags = 0; + asset_descriptor_base asset_info{}; + if (!m_wallet->get_asset_info(de.asset_id, asset_info, asset_flags)) + { + fail_msg_writer() << "unknown asset id: " << de.asset_id; + return true; + } + + bool ok = currency::parse_amount(local_args[i + 1], de.amount, asset_info.decimal_point); + if (!ok || 0 == de.amount) + { + fail_msg_writer() << "amount is wrong: " << local_args[i] << ' ' << local_args[i + 1] << + ", expected number from 0 to " << print_money_brief(std::numeric_limits::max(), asset_info.decimal_point) << " with maximum " << (int)asset_info.decimal_point << " digits after decimal point"; + return true; + } + //check if address looks like wrapped address if (is_address_like_wrapped(local_args[i])) From fe3a0ea39a95daade4ae341c06ad4b33f17b3cc0 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 2 Jul 2024 20:54:41 +0200 Subject: [PATCH 46/53] wallet: fixed incorrect decimal point for some log messages and not_enough_money error --- src/wallet/wallet2.cpp | 74 ++++++++++++++++++++++++++++---------- src/wallet/wallet2.h | 3 +- src/wallet/wallet_errors.h | 10 +++--- 3 files changed, 64 insertions(+), 23 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index e68e4657..384b9a1b 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3851,6 +3851,28 @@ bool wallet2::get_asset_info(const crypto::public_key& asset_id, currency::asset return false; } //---------------------------------------------------------------------------------------------------- +size_t wallet2::get_asset_decimal_point(const crypto::public_key& asset_id) const +{ + if (asset_id == currency::native_coin_asset_id) + return currency::get_native_coin_asset_descriptor().decimal_point; + + // whitelisted? + auto it_white = m_whitelisted_assets.find(asset_id); + if (it_white != m_whitelisted_assets.end()) + return it_white->second.decimal_point; + + // custom asset? + auto it_cust = m_custom_assets.find(asset_id); + if (it_cust != m_custom_assets.end()) + return it_cust->second.decimal_point; + + auto it_own = m_own_asset_descriptors.find(asset_id); + if (it_own != m_own_asset_descriptors.end()) + return it_own->second.decimal_point; + + return CURRENCY_DISPLAY_DECIMAL_POINT; // fallback to the default +} +//---------------------------------------------------------------------------------------------------- uint64_t wallet2::balance() const { @@ -6204,7 +6226,7 @@ bool wallet2::accept_ionic_swap_proposal(const wallet_public::ionic_swap_proposa { if (balances[item.asset_id].unlocked < item.amount) { - WLT_THROW_IF_FALSE_WALLET_EX_MES(false, error::not_enough_money, "", balances[item.asset_id].unlocked, item.amount, 0 /*fee*/, item.asset_id); + WLT_THROW_IF_FALSE_WALLET_EX_MES(false, error::not_enough_money, "", balances[item.asset_id].unlocked, item.amount, 0 /*fee*/, item.asset_id, get_asset_decimal_point(item.asset_id)); } if (item.asset_id == currency::native_coin_asset_id) { @@ -6557,10 +6579,13 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, bool use_all_decoys src.real_output = interted_it - src.outputs.begin(); src.real_output_in_tx_index = td.m_internal_output_index; - std::stringstream ss; - ss << "source entry [" << i << "], td_idx: " << J << ", "; - print_source_entry(ss, src); - WLT_LOG_L1(ss.str()); + if (epee::log_space::get_set_log_detalisation_level() >= LOG_LEVEL_1) + { + std::stringstream ss; + ss << "source entry [" << i << "], td_idx: " << J << ", "; + print_source_entry(ss, src); + WLT_LOG_L1(ss.str()); + } ++i; } @@ -7056,10 +7081,17 @@ bool wallet2::select_indices_for_transfer(assets_selection_context& needed_money { if(item.second.needed_amount == 0) continue; - auto asset_cashe_it = m_found_free_amounts.find(item.first); - WLT_THROW_IF_FALSE_WALLET_EX_MES(asset_cashe_it != m_found_free_amounts.end(), error::not_enough_money, "", item.second.found_amount, item.second.needed_amount, 0, item.first); - item.second.found_amount = select_indices_for_transfer(selected_indexes, asset_cashe_it->second, item.second.needed_amount, fake_outputs_count); - WLT_THROW_IF_FALSE_WALLET_EX_MES(item.second.found_amount >= item.second.needed_amount, error::not_enough_money, "", item.second.found_amount, item.second.needed_amount, 0, item.first); + + const crypto::public_key asset_id = item.first; + asset_descriptor_base asset_info{}; + uint32_t asset_flags = 0; + bool r = get_asset_info(asset_id, asset_info, asset_flags); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(r, "got unknown asset id: " << asset_id); + + auto asset_cache_it = m_found_free_amounts.find(asset_id); + WLT_THROW_IF_FALSE_WALLET_EX_MES(asset_cache_it != m_found_free_amounts.end(), error::not_enough_money, "", item.second.found_amount, item.second.needed_amount, 0, asset_id, asset_info.decimal_point); + item.second.found_amount = select_indices_for_transfer(selected_indexes, asset_cache_it->second, item.second.needed_amount, fake_outputs_count, asset_id, asset_info.decimal_point); + WLT_THROW_IF_FALSE_WALLET_EX_MES(item.second.found_amount >= item.second.needed_amount, error::not_enough_money, "", item.second.found_amount, item.second.needed_amount, 0, asset_id, asset_info.decimal_point); } if (m_current_context.pconstruct_tx_param && m_current_context.pconstruct_tx_param->need_at_least_1_zc) { @@ -7081,11 +7113,13 @@ bool wallet2::select_indices_for_transfer(assets_selection_context& needed_money return true; } //---------------------------------------------------------------------------------------------------- -uint64_t wallet2::select_indices_for_transfer(std::vector& selected_indexes, free_amounts_cache_type& found_free_amounts, uint64_t needed_money, uint64_t fake_outputs_count_) +uint64_t wallet2::select_indices_for_transfer(std::vector& selected_indexes, free_amounts_cache_type& found_free_amounts, uint64_t needed_money, uint64_t fake_outputs_count_, + const crypto::public_key& asset_id, size_t decimal_point) { - WLT_LOG_GREEN("Selecting indices for transfer of " << print_money_brief(needed_money) << " with " << fake_outputs_count_ << " fake outs, found_free_amounts.size()=" << found_free_amounts.size() << "...", LOG_LEVEL_0); + WLT_LOG_GREEN("Selecting indices for transfer of " << print_money_brief(needed_money, decimal_point) << " with " << fake_outputs_count_ << " fake outs, found_free_amounts.size()=" << found_free_amounts.size() << + (asset_id == native_coin_asset_id ? std::string() : std::string(", asset_id: ") + crypto::pod_to_hex(asset_id)) << "...", LOG_LEVEL_0); uint64_t found_money = 0; - //uint64_t found_zc_input = false; + size_t outputs_found = 0; std::string selected_amounts_str; while (found_money < needed_money && found_free_amounts.size()) { @@ -7105,7 +7139,8 @@ uint64_t wallet2::select_indices_for_transfer(std::vector& selected_in found_money += it->first; selected_indexes.push_back(*it->second.begin()); WLT_LOG_L2("Selected index: " << *it->second.begin() << ", transfer_details: " << ENDL << epee::serialization::store_t_to_json(m_transfers[*it->second.begin()])); - selected_amounts_str += (selected_amounts_str.empty() ? "" : "+") + print_money_brief(it->first); + selected_amounts_str += (selected_amounts_str.empty() ? "" : "+") + print_money_brief(it->first, decimal_point); + ++outputs_found; } it->second.erase(it->second.begin()); if (!it->second.size()) @@ -7113,7 +7148,8 @@ uint64_t wallet2::select_indices_for_transfer(std::vector& selected_in } - WLT_LOG_GREEN("Found " << print_money_brief(found_money) << " as " << selected_indexes.size() << " out(s): " << selected_amounts_str << ", found_free_amounts.size()=" << found_free_amounts.size(), LOG_LEVEL_0); + WLT_LOG_GREEN("Found " << print_money_brief(found_money, decimal_point) << " as " << outputs_found << " out(s): " << selected_amounts_str << ", found_free_amounts.size()=" << found_free_amounts.size() << + (asset_id == native_coin_asset_id ? std::string() : std::string(", asset_id: ") + crypto::pod_to_hex(asset_id)), LOG_LEVEL_0); return found_money; } //---------------------------------------------------------------------------------------------------- @@ -7337,13 +7373,15 @@ void wallet2::print_source_entry(std::stringstream& output, const currency::tx_s for(auto& el : src.outputs) ss << el.out_reference << " "; - output << "amount: " << print_money_brief(src.amount) << (src.is_zc() ? " (hidden)" : "") - << ", real_output: " << src.real_output + output << "amount: " << print_money_brief(src.amount, get_asset_decimal_point(src.asset_id)) << (src.is_zc() ? "" : " (bare)"); + + if (src.asset_id != currency::native_coin_asset_id) + output << " (" << print16(src.asset_id) << ")"; + + output << ", real_output: " << src.real_output << ", real_output_in_tx_index: " << src.real_output_in_tx_index << ", indexes: " << ss.str(); - if (src.asset_id != currency::native_coin_asset_id) - output << ", asset_id: " << print16(src.asset_id); } //---------------------------------------------------------------------------------------------------- bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key) const diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 448af662..09019724 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -444,6 +444,7 @@ namespace tools enum asset_info_flags_t : uint32_t { aif_none = 0, aif_whitelisted = 1 << 0, aif_own = 1 << 1 }; bool get_asset_info(const crypto::public_key& asset_id, currency::asset_descriptor_base& asset_info, uint32_t& asset_flags) const; + size_t get_asset_decimal_point(const crypto::public_key& asset_id) const; void transfer(uint64_t amount, const currency::account_public_address& acc, const crypto::public_key& asset_id = currency::native_coin_asset_id); void transfer(uint64_t amount, size_t fake_outs_count, const currency::account_public_address& acc, uint64_t fee = TX_DEFAULT_FEE, const crypto::public_key& asset_id = currency::native_coin_asset_id); @@ -607,7 +608,7 @@ namespace tools bool is_transfer_ready_to_go(const transfer_details& td, uint64_t fake_outputs_count) const; bool is_transfer_able_to_go(const transfer_details& td, uint64_t fake_outputs_count) const; - uint64_t select_indices_for_transfer(std::vector& ind, free_amounts_cache_type& found_free_amounts, uint64_t needed_money, uint64_t fake_outputs_count); + uint64_t select_indices_for_transfer(std::vector& ind, free_amounts_cache_type& found_free_amounts, uint64_t needed_money, uint64_t fake_outputs_count, const crypto::public_key& asset_id, size_t decimal_point); bool select_indices_for_transfer(assets_selection_context& needed_money_map, uint64_t fake_outputs_count, std::vector& selected_indexes); //PoS diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index bfab00d5..90dbf48c 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -350,12 +350,13 @@ namespace tools //---------------------------------------------------------------------------------------------------- struct not_enough_money : public transfer_error { - not_enough_money(std::string&& loc, uint64_t availbable, uint64_t tx_amount, uint64_t fee, const crypto::public_key& asset_id) + not_enough_money(std::string&& loc, uint64_t availbable, uint64_t tx_amount, uint64_t fee, const crypto::public_key& asset_id, size_t decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT) : transfer_error(std::move(loc), "") , m_available(availbable) , m_tx_amount(tx_amount) , m_fee(fee) , m_asset_id(asset_id) + , m_decimal_point(decimal_point) { } @@ -367,9 +368,9 @@ namespace tools { std::ostringstream ss; ss << transfer_error::to_string() << - "available: " << currency::print_money_brief(m_available) << - ", required: " << currency::print_money_brief(m_tx_amount + m_fee) << - " = " << currency::print_money_brief(m_tx_amount) << " + " << currency::print_money_brief(m_fee) << " (fee)"; + "available: " << currency::print_money_brief(m_available, m_decimal_point) << + ", required: " << currency::print_money_brief(m_tx_amount + m_fee, m_decimal_point) << + " = " << currency::print_money_brief(m_tx_amount, m_decimal_point) << " + " << currency::print_money_brief(m_fee) << " (fee)"; if (m_asset_id != currency::native_coin_asset_id) ss << ", asset_id: " << m_asset_id; return ss.str(); @@ -380,6 +381,7 @@ namespace tools uint64_t m_tx_amount; uint64_t m_fee; crypto::public_key m_asset_id; + size_t m_decimal_point; }; struct no_zc_inputs : public transfer_error From 28d841d1141e85dac9e541589c0aed20fe795737 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 2 Jul 2024 20:57:00 +0200 Subject: [PATCH 47/53] wallet: fixed non-native coins error, incorrect mixin count and tx regeneration in sweep_below() --- src/wallet/wallet2.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 384b9a1b..9a573564 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -7862,7 +7862,7 @@ void wallet2::transfer(construct_tx_param& ctp, void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public_address& destination_addr, uint64_t threshold_amount, const currency::payment_id_t& payment_id, uint64_t fee, size_t& outs_total, uint64_t& amount_total, size_t& outs_swept, uint64_t& amount_swept, currency::transaction* p_result_tx /* = nullptr */, std::string* p_filename_or_unsigned_tx_blob_str /* = nullptr */) { - static const size_t estimated_bytes_per_input = 78; + static const size_t estimated_bytes_per_input = 85; const size_t estimated_max_inputs = static_cast(CURRENCY_MAX_TRANSACTION_BLOB_SIZE / (estimated_bytes_per_input * (fake_outs_count + 1.5))); // estimated number of maximum tx inputs under the tx size limit const size_t tx_sources_for_querying_random_outs_max = estimated_max_inputs * 2; @@ -7877,9 +7877,10 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public for (uint64_t i = 0; i < m_transfers.size(); ++i) { const transfer_details& td = m_transfers[i]; + size_t fake_outs_count_for_td = is_auditable() ? 0 : (td.is_zc() ? m_core_runtime_config.hf4_minimum_mixins : fake_outs_count); uint64_t amount = td.amount(); - if (amount < threshold_amount && - is_transfer_ready_to_go(td, fake_outs_count)) + if (amount < threshold_amount && td.is_native_coin() && + is_transfer_ready_to_go(td, fake_outs_count_for_td)) { selected_transfers.push_back(i); outs_total += 1; @@ -7955,9 +7956,12 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public auto try_construct_tx = [this, &selected_transfers, &rpc_get_random_outs_resp, &fake_outs_count, &fee, &destination_addr] (size_t st_index_upper_boundary, currency::finalize_tx_param& ftp, uint64_t& amount_swept) -> try_construct_result_t { - // prepare inputs amount_swept = 0; + ftp.gen_context = tx_generation_context{}; ftp.sources.clear(); + ftp.prepared_destinations.clear(); + + // prepare inputs ftp.sources.resize(st_index_upper_boundary); WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(st_index_upper_boundary <= selected_transfers.size(), "index_upper_boundary = " << st_index_upper_boundary << ", selected_transfers.size() = " << selected_transfers.size()); for (size_t st_index = 0; st_index < st_index_upper_boundary; ++st_index) @@ -8052,7 +8056,7 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public size_t st_index_upper_boundary = std::min(selected_transfers.size(), estimated_max_inputs); try_construct_result_t res = try_construct_tx(st_index_upper_boundary, ftp, amount_swept); - + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(res != rc_too_few_outputs, st_index_upper_boundary << " biggest unspent outputs have total amount of " << print_money_brief(amount_swept) << " which is less than required fee: " << print_money_brief(fee) << ", transaction cannot be constructed"); @@ -8126,10 +8130,10 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public transaction local_tx; transaction* p_tx = p_result_tx != nullptr ? p_result_tx : &local_tx; - *p_tx = AUTO_VAL_INIT_T(transaction); + *p_tx = transaction{}; try { - crypto::secret_key sk = AUTO_VAL_INIT(sk); + crypto::secret_key sk{}; finalize_transaction(ftp, *p_tx, sk, true); } catch (...) From 95e63b7b7ec5273c4fcaf29ba3d505fc2ada31f5 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 2 Jul 2024 20:57:58 +0200 Subject: [PATCH 48/53] wallet: minor improvement for get_transfers_str (aka list_outputs): mark locked transfers with * --- src/wallet/wallet2.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 9a573564..182995fb 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3978,7 +3978,7 @@ bool wallet2::generate_utxo_defragmentation_transaction_if_needed(currency::tran //---------------------------------------------------------------------------------------------------- std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool include_unspent /*= true*/, bool show_only_unknown /*= false*/, const std::string& filter_asset_ticker /*= std::string{}*/) const { - static const char* header = "index amount ticker g_index flags block tx out# asset id"; + static const char* header = " index amount ticker g_index flags block tx out# asset id"; std::stringstream ss; ss << header << ENDL; size_t count = 0; @@ -3990,6 +3990,7 @@ std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool inclu if ((td.is_spent() && !include_spent) || (!td.is_spent() && !include_unspent)) continue; + bool is_locked = !is_transfer_unlocked(td); bool native_coin = td.is_native_coin(); asset_descriptor_base adb{}; uint32_t asset_info_flags{}; @@ -4003,7 +4004,7 @@ std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool inclu if (!filter_asset_ticker.empty() && adb.ticker != filter_asset_ticker) continue; - ss << std::right << + ss << std::right << (is_locked ? "*" : " ") << std::setw(5) << i << " " << std::setw(21) << print_asset_money(td.m_amount, adb.decimal_point) << " " << std::setw(6) << std::left << (native_coin ? std::string(" ") : adb.ticker) << " " << std::right << From 8aa1654a3fa29398c432319b5c50b9e35a766b03 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 2 Jul 2024 20:59:07 +0200 Subject: [PATCH 49/53] === build number: 321 -> 322 === --- src/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h.in b/src/version.h.in index d2dacde9..af1d8370 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -8,6 +8,6 @@ #define PROJECT_REVISION "0" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 321 +#define PROJECT_VERSION_BUILD_NO 322 #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 "]" From 3154c7b72d216f7f2540565513cbca46f6798da4 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 3 Jul 2024 01:40:40 +0200 Subject: [PATCH 50/53] fixed select_indices_for_transfer() + several improvements to decimal_point=0 support --- contrib/epee/include/print_fixed_point_helper.h | 4 +++- src/currency_core/currency_basic.h | 2 +- src/currency_core/currency_format_utils.cpp | 2 +- src/currency_core/currency_format_utils.h | 13 +++++++++---- src/wallet/wallet2.cpp | 6 +++--- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/contrib/epee/include/print_fixed_point_helper.h b/contrib/epee/include/print_fixed_point_helper.h index c652f601..91de1dd4 100644 --- a/contrib/epee/include/print_fixed_point_helper.h +++ b/contrib/epee/include/print_fixed_point_helper.h @@ -1,3 +1,4 @@ +// Copyright (c) 2024, Zano Project // Copyright (c) 2006-2017, Andrey N. Sabelnikov, www.sabelnikov.net // All rights reserved. // @@ -39,7 +40,8 @@ namespace epee { s.insert(0, decimal_point + 1 - s.size(), '0'); } - s.insert(s.size() - decimal_point, "."); + if (decimal_point > 0) + s.insert(s.size() - decimal_point, "."); return s; } } diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h index 771ae1a8..0d3e5891 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -700,7 +700,7 @@ namespace currency { uint64_t total_max_supply = 0; uint64_t current_supply = 0; - uint8_t decimal_point = 12; + uint8_t decimal_point = 0; std::string ticker; std::string full_name; std::string meta_info; diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index ce80baf3..c28a212d 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -3467,7 +3467,7 @@ namespace currency uint64_t remainder = amount % coin; amount /= coin; if (remainder == 0) - return std::to_string(amount) + ".0"; + return std::to_string(amount) + (decimal_point > 0 ? ".0" : ""); std::string r = std::to_string(remainder); if (r.size() < decimal_point) r.insert(0, decimal_point - r.size(), '0'); diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index 66fcce6a..17d6711e 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -610,20 +610,25 @@ namespace currency return true; } //--------------------------------------------------------------- - // outputs "1391306.970000000000" + // outputs "1391306.970000000000" (decimal_point = 12) + // outputs "1391306970000000000" (decimal_point = 0) template std::string print_fixed_decimal_point(t_number amount, size_t decimal_point) { return epee::string_tools::print_fixed_decimal_point(amount, decimal_point); } //--------------------------------------------------------------- - // outputs "1391306.97 " + // outputs "1391306.97 " (decimal_point = 12) + // outputs "139130697 " (decimal_point = 0) template std::string print_fixed_decimal_point_with_trailing_spaces(t_number amount, size_t decimal_point) { std::string s = epee::string_tools::print_fixed_decimal_point(amount, decimal_point); - for(size_t n = s.size() - 1; n != 0 && s[n] == '0' && s[n-1] != '.'; --n) - s[n] = ' '; + if (s.find('.') != std::string::npos) + { + for(size_t n = s.size() - 1; n != 0 && s[n] == '0' && s[n-1] != '.'; --n) + s[n] = ' '; + } return s; } //--------------------------------------------------------------- diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 182995fb..b4bb5b65 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3870,7 +3870,7 @@ size_t wallet2::get_asset_decimal_point(const crypto::public_key& asset_id) cons if (it_own != m_own_asset_descriptors.end()) return it_own->second.decimal_point; - return CURRENCY_DISPLAY_DECIMAL_POINT; // fallback to the default + return 0; // fallback to the 0 decimal point (raw numbers) as the default } //---------------------------------------------------------------------------------------------------- @@ -7086,8 +7086,8 @@ bool wallet2::select_indices_for_transfer(assets_selection_context& needed_money const crypto::public_key asset_id = item.first; asset_descriptor_base asset_info{}; uint32_t asset_flags = 0; - bool r = get_asset_info(asset_id, asset_info, asset_flags); - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(r, "got unknown asset id: " << asset_id); + if (!get_asset_info(asset_id, asset_info, asset_flags)) + WLT_LOG_L1("select_indices_for_transfer: unknown asset id: " << asset_id); auto asset_cache_it = m_found_free_amounts.find(asset_id); WLT_THROW_IF_FALSE_WALLET_EX_MES(asset_cache_it != m_found_free_amounts.end(), error::not_enough_money, "", item.second.found_amount, item.second.needed_amount, 0, asset_id, asset_info.decimal_point); From a6808b4646a7199096844d6861c67659b3185912 Mon Sep 17 00:00:00 2001 From: zano build machine Date: Wed, 3 Jul 2024 05:37:56 +0300 Subject: [PATCH 51/53] === build number: 322 -> 323 === --- src/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h.in b/src/version.h.in index af1d8370..dfcbb22e 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -8,6 +8,6 @@ #define PROJECT_REVISION "0" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 322 +#define PROJECT_VERSION_BUILD_NO 323 #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 "]" From 3d69468cfd36e650d9729e4542c69d45efe0cf35 Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 4 Jul 2024 20:11:11 +0200 Subject: [PATCH 52/53] wallet2: minor improvements for get_balance_str_raw() and get_asset_decimal_point() --- src/wallet/wallet2.cpp | 55 +++++++++++++++++++++++++++++------------- src/wallet/wallet2.h | 5 ++-- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index b4bb5b65..e9a8a8f1 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3851,7 +3851,7 @@ bool wallet2::get_asset_info(const crypto::public_key& asset_id, currency::asset return false; } //---------------------------------------------------------------------------------------------------- -size_t wallet2::get_asset_decimal_point(const crypto::public_key& asset_id) const +size_t wallet2::get_asset_decimal_point(const crypto::public_key& asset_id, size_t result_if_not_found /* = 0 */) const { if (asset_id == currency::native_coin_asset_id) return currency::get_native_coin_asset_descriptor().decimal_point; @@ -3870,10 +3870,19 @@ size_t wallet2::get_asset_decimal_point(const crypto::public_key& asset_id) cons if (it_own != m_own_asset_descriptors.end()) return it_own->second.decimal_point; - return 0; // fallback to the 0 decimal point (raw numbers) as the default + return result_if_not_found; // if not overriden, use the 0 decimal point (raw numbers) as the default +} +//---------------------------------------------------------------------------------------------------- +bool wallet2::get_asset_decimal_point(const crypto::public_key& asset_id, size_t* p_decimal_point_result) const +{ + size_t decimal_point = get_asset_decimal_point(asset_id, SIZE_MAX); + if (decimal_point == SIZE_MAX) + return false; + if (p_decimal_point_result != nullptr) + *p_decimal_point_result = decimal_point; + return true; } //---------------------------------------------------------------------------------------------------- - uint64_t wallet2::balance() const { uint64_t stub = 0; @@ -4035,9 +4044,10 @@ std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool inclu std::string wallet2::get_balance_str() const { // balance unlocked / [balance total] ticker asset id - // 1391306.970000000000 / 1391306.970000000000 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a - // 1391306.97 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a - // 106.971 / 206.4 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a + // 0.21 / 98.51 DP2 a6974d5874e97e5f4ed5ad0a62f0975edbccb1bb55502fc75c7fe808f12f44d3 + // 190.123456789012 / 199.123456789012 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a + // 98.0 BGTVUW af2b12f3033337f9aea1845a6bc3fc966ed4d13227a3ace7706fca7dbcdaa7e2 + // 1000.034 DP3 d4aba1020f26927571771e04b585b4ffb211f52708d5e4c465bbdfa4a12e6271 static const char* header = " balance unlocked / [balance total] ticker asset id"; std::stringstream ss; @@ -4061,12 +4071,16 @@ std::string wallet2::get_balance_str() const //---------------------------------------------------------------------------------------------------- std::string wallet2::get_balance_str_raw() const { - // balance unlocked / [balance total] ticker asset id - // 1391306.970000000000 / 1391306.970000000000 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a - // 1391306.97 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a - // 106.971 / 206.4 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a + // balance unlocked / [balance total] DP asset id + // 0.21 / 98.51 2 a6974d5874e97e5f4ed5ad0a62f0975edbccb1bb55502fc75c7fe808f12f44d3 + // 190.123456789012 / 199.123456789012 12 d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a + // 98.0 12 af2b12f3033337f9aea1845a6bc3fc966ed4d13227a3ace7706fca7dbcdaa7e2 + // 1000.034 3 d4aba1020f26927571771e04b585b4ffb211f52708d5e4c465bbdfa4a12e6271 + //WHITELIST: + // 7d3f348fbebfffc4e61a3686189cf870ea393e1c88b8f636acbfdacf9e4b2db2 CT + // ... - static const char* header = " balance unlocked / [balance total] asset id"; + static const char* header = " balance unlocked / [balance total] DP asset id"; std::stringstream ss; ss << header << ENDL; @@ -4076,32 +4090,39 @@ std::string wallet2::get_balance_str_raw() const for(const auto& entry : balances_map) { - ss << " " << std::left << std::setw(20) << print_fixed_decimal_point_with_trailing_spaces(entry.second.unlocked, 12); + size_t decimal_point = 0; + bool has_known_decimal_point = get_asset_decimal_point(entry.first, &decimal_point); + ss << " " << std::left << std::setw(20) << print_fixed_decimal_point_with_trailing_spaces(entry.second.unlocked, decimal_point); if(entry.second.total == entry.second.unlocked) ss << " "; else - ss << " / " << std::setw(20) << print_fixed_decimal_point_with_trailing_spaces(entry.second.total, 12); - ss << " " << std::setw(8) << std::left << entry.first << ENDL; + ss << " / " << std::setw(20) << print_fixed_decimal_point_with_trailing_spaces(entry.second.total, decimal_point); + + if (has_known_decimal_point) + ss << std::setw(2) << std::right << decimal_point; + else + ss << "??"; + + ss << " " << entry.first << ENDL; } //print whitelist ss << "WHITELIST: " << ENDL; - for(const auto& entry : m_whitelisted_assets) { ss << " " << std::left << entry.first << " " << entry.second.ticker << ENDL; } - // print whitelist + // print custom list ss << "CUSTOM LIST: " << ENDL; - for(const auto& entry : m_custom_assets) { ss << " " << std::left << entry.first << " " << entry.second.ticker << ENDL; } + // print own list ss << "OWN DESCRIPTORS LIST: " << ENDL; for(const auto& entry : m_own_asset_descriptors) diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 09019724..2fa7601b 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -444,8 +444,9 @@ namespace tools enum asset_info_flags_t : uint32_t { aif_none = 0, aif_whitelisted = 1 << 0, aif_own = 1 << 1 }; bool get_asset_info(const crypto::public_key& asset_id, currency::asset_descriptor_base& asset_info, uint32_t& asset_flags) const; - size_t get_asset_decimal_point(const crypto::public_key& asset_id) const; - + size_t get_asset_decimal_point(const crypto::public_key& asset_id, size_t result_if_not_found = 0) const; + bool get_asset_decimal_point(const crypto::public_key& asset_id, size_t* p_decimal_point_result) const; + void transfer(uint64_t amount, const currency::account_public_address& acc, const crypto::public_key& asset_id = currency::native_coin_asset_id); void transfer(uint64_t amount, size_t fake_outs_count, const currency::account_public_address& acc, uint64_t fee = TX_DEFAULT_FEE, const crypto::public_key& asset_id = currency::native_coin_asset_id); void transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx, const crypto::public_key& asset_id = currency::native_coin_asset_id); From d0c65a04e76172515a47a7ff7a4585c11f7c6952 Mon Sep 17 00:00:00 2001 From: zano build machine Date: Thu, 4 Jul 2024 21:13:27 +0300 Subject: [PATCH 53/53] === build number: 323 -> 324 === --- src/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h.in b/src/version.h.in index dfcbb22e..26d965ed 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -8,6 +8,6 @@ #define PROJECT_REVISION "0" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 323 +#define PROJECT_VERSION_BUILD_NO 324 #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 "]"