1
0
Fork 0
forked from lthn/blockchain

Merge branch 'multiassets' into zarcanum

This commit is contained in:
sowle 2022-10-13 15:17:02 +02:00
commit 2c88652fbd
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
39 changed files with 889 additions and 100 deletions

View file

@ -103,7 +103,7 @@ else()
else()
set(ARCH_FLAG "-march=${ARCH}")
endif()
set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=deprecated-declarations -Wno-error=sign-compare -Wno-error=strict-aliasing -Wno-error=type-limits -Wno-unused-parameter -Wno-error=unused-variable -Wno-aggregate-return -Wno-comment")
set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=deprecated-declarations -Wno-error=sign-compare -Wno-error=strict-aliasing -Wno-error=type-limits -Wno-unused-parameter -Wno-error=unused-variable -Wno-aggregate-return -Wno-comment -Wno-unknown-pragmas -Wno-pragmas")
# if(NOT APPLE)
# set(WARNINGS "${WARNINGS} -Werror")
# endif()
@ -135,7 +135,7 @@ else()
else()
set(APPLE_FLAG "")
endif()
set(C_WARNINGS "-Waggregate-return -Wnested-externs -Wstrict-prototypes")
set(C_WARNINGS "-Waggregate-return -Wnested-externs -Wstrict-prototypes -Wno-comment")
set(CXX_WARNINGS "-Wno-reorder -Wno-missing-field-initializers")
try_compile(STATIC_ASSERT_RES "${CMAKE_CURRENT_BINARY_DIR}/static-assert" "${CMAKE_CURRENT_SOURCE_DIR}/utils/test-static-assert.c" COMPILE_DEFINITIONS "-std=c++14")
if(STATIC_ASSERT_RES)

View file

@ -1261,7 +1261,7 @@ namespace log_space
enabled_channels_local.insert(ch_name);
genabled_channels.swap(enabled_channels_local);
#ifndef ANDROID_BUILD
std::cout << "log channel '" << ch_name << "' enabled" << std::endl;
//std::cout << "log channel '" << ch_name << "' enabled" << std::endl;
#endif
}

View file

@ -79,6 +79,8 @@ namespace net_utils
m_started(time(NULL))
{}
connection_context_base(const connection_context_base& a) = default;
connection_context_base& operator=(const connection_context_base& a)
{
set_details(a.m_connection_id, a.m_remote_ip, a.m_remote_port, a.m_is_income);

View file

@ -12,9 +12,13 @@
#define DISABLE_GCC_WARNING(w)
#define DISABLE_CLANG_WARNING(w)
#define DISABLE_GCC_AND_CLANG_WARNING(w)
#define ATTRIBUTE_UNUSED
#else
#define ATTRIBUTE_UNUSED __attribute__((unused))
#include <boost/preprocessor/stringize.hpp>
#define PUSH_VS_WARNINGS

@ -1 +1 @@
Subproject commit 2e7176dcea611c1933bec4133591e3f1885b8b37
Subproject commit 13f47143c0dcb8c12cfa293efc9d6d57ad3d1e37

View file

@ -291,6 +291,10 @@ namespace tools
if (res == MDB_NOTFOUND)
return false;
if (res != MDB_SUCCESS)
{
return false;
}
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_get, h: " << h << ", ks: " << ks);
res_buff.assign((const char*)data.mv_data, data.mv_size);

View file

@ -4,9 +4,9 @@
#pragma once
#define VARIANT_SWITCH_BEGIN(v_type_obj) {auto & local_reference_eokcmeokmeokcm = v_type_obj; if(false) {;
#define VARIANT_CASE_CONST(v_type, typed_name) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { const v_type& typed_name = boost::get<v_type>(local_reference_eokcmeokmeokcm);
#define VARIANT_CASE(v_type, typed_name) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { v_type& typed_name = boost::get<v_type>(local_reference_eokcmeokmeokcm);
#define VARIANT_SWITCH_BEGIN(v_type_obj) {auto & local_reference_eokcmeokmeokcm ATTRIBUTE_UNUSED = v_type_obj; if(false) {;
#define VARIANT_CASE_CONST(v_type, typed_name) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { const v_type& typed_name ATTRIBUTE_UNUSED = boost::get<v_type>(local_reference_eokcmeokmeokcm);
#define VARIANT_CASE(v_type, typed_name) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { v_type& typed_name ATTRIBUTE_UNUSED = boost::get<v_type>(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());

View file

@ -7,7 +7,7 @@
#include <assert.h>
#include <string.h>
#include "warnings.h"
//#include <compat/cpuid.h>
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
@ -462,6 +462,9 @@ namespace
TransformD64Type TransformD64_4way = nullptr;
TransformD64Type TransformD64_8way = nullptr;
PUSH_GCC_WARNINGS
DISABLE_GCC_AND_CLANG_WARNING(unused-function)
bool SelfTest() {
// Input state (equal to the initial SHA256 state)
static const uint32_t init[8] = {
@ -626,7 +629,7 @@ std::string SHA256AutoDetect()
assert(SelfTest());
return ret;
}
POP_GCC_WARNINGS
////// SHA-256
CSHA256::CSHA256() : bytes(0)

View file

@ -14,7 +14,7 @@ namespace crypto
#define DBG_VAL_PRINT(x) (void(0)) // std::cout << #x ": " << x << std::endl
#define DBG_PRINT(x) (void(0)) // std::cout << x << std::endl
static std::ostream &operator <<(std::ostream &o, const crypto::hash &v) { return o << pod_to_hex(v); }
//static std::ostream &operator <<(std::ostream &o, const crypto::hash &v) { return o << pod_to_hex(v); }
bool generate_CLSAG_GG(const hash& m, const std::vector<CLSAG_GG_input_ref_t>& ring, const point_t& pseudo_out_amount_commitment, const key_image& ki,
const scalar_t& secret_x, const scalar_t& secret_f, uint64_t secret_index, CLSAG_GG_signature& sig)

View file

@ -141,8 +141,7 @@ namespace crypto
crypto::secret_key m_sk;
};
scalar_t()
{}
scalar_t() = default;
// won't check scalar range validity (< L)
scalar_t(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3)
@ -844,8 +843,11 @@ namespace crypto
// zeroes all elements
void zero()
{
PUSH_GCC_WARNINGS
DISABLE_GCC_AND_CLANG_WARNING(class-memaccess)
size_t size_bytes = sizeof(scalar_t) * size();
memset(data(), 0, size_bytes);
POP_GCC_WARNINGS
}
// invert all elements in-place efficiently: 4*N muptiplications + 1 inversion
@ -1157,6 +1159,15 @@ namespace crypto
return hs_calculator.calc_hash();
}
static scalar_t hs(const char(&str32)[32], const crypto::key_derivation& derivation, uint64_t index)
{
hs_t hs_calculator(3);
hs_calculator.add_32_chars(str32);
hs_calculator.add_pub_key(reinterpret_cast<const crypto::public_key&>(derivation));
hs_calculator.add_scalar(index);
return hs_calculator.calc_hash();
}
static point_t hp(const point_t& p)
{
point_t result;
@ -1195,7 +1206,6 @@ namespace crypto
{
// hs won't touch memory if size is 0, so it's safe
return hash_helper_t::hs(data(), sizeof(scalar_t) * size());
}
}
} // namespace crypto

View file

@ -59,6 +59,7 @@ using namespace currency;
#define BLOCKCHAIN_STORAGE_CONTAINER_ADDR_TO_ALIAS "addr_to_alias"
#define BLOCKCHAIN_STORAGE_CONTAINER_TX_FEE_MEDIAN "median_fee2"
#define BLOCKCHAIN_STORAGE_CONTAINER_GINDEX_INCS "gindex_increments"
#define BLOCKCHAIN_STORAGE_CONTAINER_ASSETS "assets"
#define BLOCKCHAIN_STORAGE_OPTIONS_ID_CURRENT_BLOCK_CUMUL_SZ_LIMIT 0
#define BLOCKCHAIN_STORAGE_OPTIONS_ID_CURRENT_PRUNED_RS_HEIGHT 1
@ -95,6 +96,7 @@ blockchain_storage::blockchain_storage(tx_memory_pool& tx_pool) :m_db(nullptr, m
m_db_multisig_outs(m_db),
m_db_solo_options(m_db),
m_db_aliases(m_db),
m_db_assets(m_db),
m_db_addr_to_alias(m_db),
m_read_lock(m_rw_lock),
m_db_current_block_cumul_sz_limit(BLOCKCHAIN_STORAGE_OPTIONS_ID_CURRENT_BLOCK_CUMUL_SZ_LIMIT, m_db_solo_options),
@ -279,6 +281,8 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
CHECK_AND_ASSERT_MES(res, false, "Unable to init db container");
res = m_db_aliases.init(BLOCKCHAIN_STORAGE_CONTAINER_ALIASES);
CHECK_AND_ASSERT_MES(res, false, "Unable to init db container");
res = m_db_assets.init(BLOCKCHAIN_STORAGE_CONTAINER_ASSETS);
CHECK_AND_ASSERT_MES(res, false, "Unable to init db container");
res = m_db_addr_to_alias.init(BLOCKCHAIN_STORAGE_CONTAINER_ADDR_TO_ALIAS);
CHECK_AND_ASSERT_MES(res, false, "Unable to init db container");
res = m_db_per_block_gindex_incs.init(BLOCKCHAIN_STORAGE_CONTAINER_GINDEX_INCS);
@ -297,6 +301,7 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
m_db_multisig_outs.set_cache_size(cache_size);
m_db_solo_options.set_cache_size(cache_size);
m_db_aliases.set_cache_size(cache_size);
m_db_assets.set_cache_size(cache_size);
m_db_addr_to_alias.set_cache_size(cache_size);
}
@ -414,6 +419,7 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
m_db_multisig_outs.deinit();
m_db_solo_options.deinit();
m_db_aliases.deinit();
m_db_assets.deinit();
m_db_addr_to_alias.deinit();
m_db_per_block_gindex_incs.deinit();
m_db.close();
@ -660,6 +666,7 @@ bool blockchain_storage::clear()
m_db_outputs.clear();
m_db_multisig_outs.clear();
m_db_aliases.clear();
m_db_assets.clear();
m_db_addr_to_alias.clear();
m_db_per_block_gindex_incs.clear();
m_pos_targetdata_cache.clear();
@ -1549,6 +1556,7 @@ void blockchain_storage::reset_db_cache() const
m_db_solo_options.clear_cache();
m_db_multisig_outs.clear_cache();
m_db_aliases.clear_cache();
m_db_assets.clear_cache();
m_db_addr_to_alias.clear_cache();
}
@ -2949,6 +2957,7 @@ void blockchain_storage::print_db_cache_perfeormance_data() const
DB_CONTAINER_PERF_DATA_ENTRY(m_db_multisig_outs) << ENDL
DB_CONTAINER_PERF_DATA_ENTRY(m_db_solo_options) << ENDL
DB_CONTAINER_PERF_DATA_ENTRY(m_db_aliases) << ENDL
DB_CONTAINER_PERF_DATA_ENTRY(m_db_assets) << ENDL
DB_CONTAINER_PERF_DATA_ENTRY(m_db_addr_to_alias) << ENDL
//DB_CONTAINER_PERF_DATA_ENTRY(m_db_per_block_gindex_incs) << ENDL
//DB_CONTAINER_PERF_DATA_ENTRY(m_tx_fee_median) << ENDL
@ -3490,6 +3499,22 @@ bool blockchain_storage::unprocess_blockchain_tx_extra(const transaction& tx)
r = pop_alias_info(ei.m_alias);
CHECK_AND_ASSERT_MES(r, false, "failed to pop_alias_info");
}
if (ei.m_asset_operation.operation_type != ASSET_DESCRIPTOR_OPERATION_UNDEFINED)
{
crypto::hash asset_id = currency::null_hash;
if (ei.m_asset_operation.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER)
{
asset_id = get_asset_id_from_descriptor(ei.m_asset_operation.descriptor);
}
else
{
CHECK_AND_ASSERT_MES(ei.m_asset_operation.asset_id.size() == 1, false, "Unexpected asset_id in operation");
asset_id = ei.m_asset_operation.asset_id.back();
}
r = pop_asset_info(asset_id);
CHECK_AND_ASSERT_MES(r, false, "failed to pop_alias_info");
}
return true;
}
//------------------------------------------------------------------
@ -3514,6 +3539,27 @@ uint64_t blockchain_storage::get_aliases_count() const
return m_db_aliases.size();
}
//------------------------------------------------------------------
bool blockchain_storage::get_asset_info(const crypto::hash& asset_id, asset_descriptor_base& info)const
{
CRITICAL_REGION_LOCAL(m_read_lock);
auto as_ptr = m_db_assets.find(asset_id);
if (as_ptr)
{
if (as_ptr->size())
{
info = as_ptr->back().descriptor;
return true;
}
}
return false;
}
//------------------------------------------------------------------
uint64_t blockchain_storage::get_assets_count() const
{
CRITICAL_REGION_LOCAL(m_read_lock);
return m_db_assets.size();
}
//------------------------------------------------------------------
std::string blockchain_storage::get_alias_by_address(const account_public_address& addr)const
{
auto alias_ptr = m_db_addr_to_alias.find(addr);
@ -3696,6 +3742,48 @@ bool blockchain_storage::put_alias_info(const transaction & tx, extra_alias_entr
return true;
}
//------------------------------------------------------------------
bool blockchain_storage::pop_asset_info(const crypto::hash& asset_id)
{
CRITICAL_REGION_LOCAL(m_read_lock);
auto asset_history_ptr = m_db_assets.find(asset_id);
CHECK_AND_ASSERT_MES(asset_history_ptr && asset_history_ptr->size(), false, "empty name list in pop_asset_info");
assets_container::t_value_type local_asset_hist = *asset_history_ptr;
local_asset_hist.pop_back();
if (local_asset_hist.size())
m_db_assets.set(asset_id, local_asset_hist);
else
m_db_assets.erase(asset_id);
LOG_PRINT_MAGENTA("[ASSET_POP]: " << asset_id << ": " << (!local_asset_hist.empty() ? "(prev)" : "(erased)"), LOG_LEVEL_1);
return true;
}
//------------------------------------------------------------------
bool blockchain_storage::put_asset_info(const transaction & tx, asset_descriptor_operation & ado)
{
CRITICAL_REGION_LOCAL(m_read_lock);
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER)
{
crypto::hash asset_id = get_asset_id_from_descriptor(ado.descriptor);
auto asset_history_ptr = m_db_assets.find(asset_id);
CHECK_AND_ASSERT_MES(!asset_history_ptr, false, "Asset id already existing");
assets_container::t_value_type local_asset_history = AUTO_VAL_INIT(local_asset_history);
local_asset_history.push_back(ado);
m_db_assets.set(asset_id, local_asset_history);
LOG_PRINT_MAGENTA("[ASSET_REGISTERED]: " << asset_id << ": " << ado.descriptor.full_name, LOG_LEVEL_1);
//TODO:
//rise_core_event(CORE_EVENT_ADD_ASSET, alias_info_to_rpc_alias_info(ai));
}
else
{
//TODO: implement other operations
CHECK_AND_ASSERT_THROW(false, "not implemented yet");
}
return true;
}
//------------------------------------------------------------------
void blockchain_storage::set_event_handler(i_core_event_handler* event_handler) const
{
if (event_handler == nullptr)
@ -3785,6 +3873,12 @@ bool blockchain_storage::process_blockchain_tx_extra(const transaction& tx)
r = put_alias_info(tx, ei.m_alias);
CHECK_AND_ASSERT_MES(r, false, "failed to put_alias_info");
}
if (ei.m_asset_operation.operation_type != ASSET_DESCRIPTOR_OPERATION_UNDEFINED)
{
r = put_asset_info(tx, ei.m_asset_operation);
CHECK_AND_ASSERT_MES(r, false, "failed to put_asset_info");
}
return true;
}
//------------------------------------------------------------------

View file

@ -288,6 +288,8 @@ namespace currency
uint64_t get_aliases_count()const;
uint64_t get_block_h_older_then(uint64_t timestamp) const;
bool validate_tx_service_attachmens_in_services(const tx_service_attachment& a, size_t i, const transaction& tx)const;
bool get_asset_info(const crypto::hash& asset_id, asset_descriptor_base& info)const;
uint64_t get_assets_count() const;
bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const;
bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const;
bool check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const;
@ -486,6 +488,9 @@ namespace currency
typedef tools::db::cached_key_value_accessor<crypto::hash, ms_output_entry, false, false> multisig_outs_container;// ms out id => ms_output_entry
typedef tools::db::cached_key_value_accessor<uint64_t, uint64_t, false, true> solo_options_container;
typedef tools::db::basic_key_value_accessor<uint32_t, block_gindex_increments, true> per_block_gindex_increments_container; // height => [(amount, gindex_increment), ...]
typedef tools::db::cached_key_value_accessor<crypto::hash, std::list<asset_descriptor_operation>, true, false> assets_container;
//-----------------------------------------
@ -527,6 +532,7 @@ namespace currency
address_to_aliases_container m_db_addr_to_alias;
per_block_gindex_increments_container m_db_per_block_gindex_incs;
assets_container m_db_assets;
@ -645,6 +651,8 @@ namespace currency
bool unprocess_blockchain_tx_attachments(const transaction& tx, uint64_t h, uint64_t timestamp);
bool pop_alias_info(const extra_alias_entry& ai);
bool put_alias_info(const transaction& tx, extra_alias_entry& ai);
bool pop_asset_info(const crypto::hash& asset_id);
bool put_asset_info(const transaction & tx, asset_descriptor_operation & ado);
void fill_addr_to_alias_dict();
//bool resync_spent_tx_flags();
bool prune_ring_signatures_and_attachments_if_need();

View file

@ -6,6 +6,7 @@
// hash domain separation strings, 32 bytes long (31 chars + \0)
//
#define CRYPTO_HDS_OUT_AMOUNT_MASK "ZANO_HDS_OUT_AMOUNT_MASK_______"
#define CRYPTO_HDS_OUT_BLINDING_MASK "ZANO_HDS_OUT_BLINDING_MASK_____"
#define CRYPTO_HDS_OUT_CONCEALING_POINT "ZANO_HDS_OUT_CONCEALING_POINT__"
@ -23,3 +24,6 @@
#define CRYPTO_HDS_ZARCANUM_LAST_POW_HASH "ZANO_HDS_ZARCANUM_LAST_POW_HASH"
#define CRYPTO_HDS_ZARCANUM_SECRET_Q "ZANO_HDS_ZARCANUM_SECRET_Q_____"
#define CRYPTO_HDS_ZARCANUM_PROOF_HASH "ZANO_HDS_ZARCANUM_PROOF_HASH___"
#define CRYPTO_HDS_ASSET_CONTROL_KEY "ZANO_HDS_ASSET_CONTROL_KEY_____"
#define CRYPTO_HDS_ASSET_ID "ZANO_HDS_ASSET_ID______________"

View file

@ -54,6 +54,8 @@ namespace currency
const static crypto::key_derivation null_derivation = AUTO_VAL_INIT(null_derivation);
const static crypto::hash gdefault_genesis = epee::string_tools::hex_to_pod<crypto::hash>("CC608F59F8080E2FBFE3C8C80EB6E6A953D47CF2D6AEBD345BADA3A1CAB99852");
const static crypto::hash ffff_hash = epee::string_tools::hex_to_pod<crypto::hash>("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
typedef std::string payment_id_t;
@ -411,6 +413,7 @@ namespace currency
FIELD(amount_commitment)
FIELD(encrypted_amount)
FIELD(mix_attr)
FIELD(etc_details)
END_SERIALIZE()
BEGIN_BOOST_SERIALIZATION()
@ -419,6 +422,7 @@ namespace currency
BOOST_SERIALIZE(amount_commitment)
BOOST_SERIALIZE(encrypted_amount)
BOOST_SERIALIZE(mix_attr)
BOOST_SERIALIZE(etc_details)
END_BOOST_SERIALIZATION()
};
@ -440,7 +444,7 @@ namespace currency
struct zc_outs_range_proof
{
crypto::bpp_signature_serialized bpp;
uint8_t outputs_count; // how many outputs are included in the proof
uint8_t outputs_count = 0; // how many outputs are included in the proof
BEGIN_SERIALIZE_OBJECT()
FIELD(bpp)
@ -456,7 +460,7 @@ namespace currency
// Zarcanum-aware CLSAG signature
struct ZC_sig
{
crypto::public_key pseudo_out_amount_commitment; // premultiplied by 1/8
crypto::public_key pseudo_out_amount_commitment = null_pkey; // premultiplied by 1/8
crypto::CLSAG_GG_signature_serialized clsags_gg;
BEGIN_SERIALIZE_OBJECT()
@ -472,7 +476,7 @@ namespace currency
struct zc_balance_proof
{
crypto::signature s;
crypto::signature s = null_sig;
BEGIN_SERIALIZE_OBJECT()
FIELD(s)
@ -704,6 +708,68 @@ namespace currency
struct asset_descriptor_base
{
uint64_t total_max_supply = 0;
uint64_t current_supply = 0;
uint8_t decimal_point = 12;
std::string ticker;
std::string full_name;
crypto::public_key owner = currency::null_pkey;
BEGIN_VERSIONED_SERIALIZE()
FIELD(total_max_supply)
FIELD(current_supply)
FIELD(decimal_point)
FIELD(ticker)
FIELD(full_name)
FIELD(owner)
END_SERIALIZE()
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(total_max_supply)
BOOST_SERIALIZE(current_supply)
BOOST_SERIALIZE(decimal_point)
BOOST_SERIALIZE(ticker)
BOOST_SERIALIZE(full_name)
BOOST_SERIALIZE(owner)
END_BOOST_SERIALIZATION()
};
#define ASSET_DESCRIPTOR_OPERATION_UNDEFINED 0
#define ASSET_DESCRIPTOR_OPERATION_REGISTER 1
#define ASSET_DESCRIPTOR_OPERATION_EMMIT 2
#define ASSET_DESCRIPTOR_OPERATION_UPDATE 3
struct asset_descriptor_operation
{
uint8_t operation_type = ASSET_DESCRIPTOR_OPERATION_UNDEFINED;
std::vector<crypto::signature> proof;
asset_descriptor_base descriptor;
std::vector<crypto::hash> asset_id; //questionable regarding form of optional fields
BEGIN_VERSIONED_SERIALIZE()
FIELD(operation_type)
FIELD(proof)
FIELD(descriptor)
FIELD(asset_id)
END_SERIALIZE()
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(operation_type)
BOOST_SERIALIZE(proof)
BOOST_SERIALIZE(descriptor)
END_BOOST_SERIALIZATION()
};
struct extra_padding
{
std::vector<uint8_t> buff; //stub
@ -768,10 +834,10 @@ namespace currency
END_SERIALIZE()
};
typedef boost::mpl::vector24<
typedef boost::mpl::vector25<
tx_service_attachment, tx_comment, tx_payer_old, tx_receiver_old, tx_derivation_hint, std::string, tx_crypto_checksum, etc_tx_time, etc_tx_details_unlock_time, etc_tx_details_expiration_time,
etc_tx_details_flags, crypto::public_key, extra_attachment_info, extra_alias_entry_old, extra_user_data, extra_padding, etc_tx_flags16_t, etc_tx_details_unlock_time2,
tx_payer, tx_receiver, extra_alias_entry, zarcanum_tx_data_v1, zc_outs_range_proof, zc_balance_proof
tx_payer, tx_receiver, extra_alias_entry, zarcanum_tx_data_v1, zc_outs_range_proof, zc_balance_proof, asset_descriptor_operation
> all_payload_types;
typedef boost::make_variant_over<all_payload_types>::type payload_items_v;
@ -1099,6 +1165,9 @@ SET_VARIANT_TAGS(currency::zc_balance_proof, 47, "zc_balance_proof");
SET_VARIANT_TAGS(currency::open_asset_id, 48, "asset_id");
SET_VARIANT_TAGS(currency::asset_descriptor_operation, 48, "asset_descriptor_base");
#undef SET_VARIANT_TAGS

View file

@ -232,7 +232,7 @@
#define BC_OFFERS_CURRENCY_MARKET_FILENAME "market.bin"
#ifndef TESTNET
#define WALLET_FILE_SERIALIZATION_VERSION 153
#define WALLET_FILE_SERIALIZATION_VERSION 154
#else
#define WALLET_FILE_SERIALIZATION_VERSION (CURRENCY_FORMATION_VERSION+69)
#endif

View file

@ -335,8 +335,16 @@ namespace currency
{
if (tx.version > TRANSACTION_VERSION_PRE_HF4)
{
//@#@ TODO: This is just a temporary code
uint64_t assets_emmited = 0;
asset_descriptor_operation ado = AUTO_VAL_INIT(ado);
if (get_type_in_variant_container(tx.extra, ado) && ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER)
{
assets_emmited += ado.descriptor.current_supply;
}
size_t zc_inputs_count = 0;
uint64_t bare_inputs_sum = additional_inputs_amount_and_fees_for_mining_tx;
uint64_t bare_inputs_sum = additional_inputs_amount_and_fees_for_mining_tx + assets_emmited;
for(auto& vin : tx.vin)
{
VARIANT_SWITCH_BEGIN(vin);
@ -655,19 +663,18 @@ namespace currency
//---------------------------------------------------------------
struct tx_extra_handler : public boost::static_visitor<bool>
{
mutable bool was_padding; //let the padding goes only at the end
mutable bool was_pubkey;
mutable bool was_attachment;
mutable bool was_userdata;
mutable bool was_alias;
mutable bool was_padding = false; //let the padding goes only at the end
mutable bool was_pubkey = false;
mutable bool was_attachment = false;
mutable bool was_userdata = false;
mutable bool was_alias = false;
mutable bool was_asset = false;
tx_extra_info& rei;
const transaction& rtx;
tx_extra_handler(tx_extra_info& ei, const transaction& tx) :rei(ei), rtx(tx)
{
was_padding = was_pubkey = was_attachment = was_userdata = was_alias = false;
}
{}
#define ENSURE_ONETIME(varname, entry_name) CHECK_AND_ASSERT_MES(varname == false, false, "double entry in tx_extra: " entry_name); varname = true;
@ -690,6 +697,12 @@ namespace currency
rei.m_alias = ae;
return true;
}
bool operator()(const asset_descriptor_operation & ado) const
{
ENSURE_ONETIME(was_asset, "asset");
rei.m_asset_operation = ado;
return true;
}
bool operator()(const extra_alias_entry_old& ae) const
{
return operator()(static_cast<const extra_alias_entry&>(ae));
@ -791,6 +804,17 @@ namespace currency
return derive_public_key_from_target_address(destination_addr, tx_sec_key, index, out_eph_public_key, derivation);
}
//---------------------------------------------------------------
bool derive_key_pair_from_key_pair(const crypto::public_key& src_pub_key, const crypto::secret_key& src_sec_key, crypto::secret_key& derived_sec_key, crypto::public_key& derived_pub_key, const char(&hs_domain)[32], uint64_t index)
{
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
bool r = crypto::generate_key_derivation(src_pub_key, src_sec_key, derivation);
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << src_pub_key << ", " << src_sec_key << ")");
crypto::scalar_t sec_key = crypto::hash_helper_t::hs(hs_domain, derivation, index);
derived_sec_key = sec_key.as_secret_key();
derived_pub_key = (sec_key * crypto::c_point_G).to_public_key();
return true;
}
//---------------------------------------------------------------
// derivation = 8 * tx_sec_key * destination_addr.view_public_key
// out_eph_public_key = destination_addr.spend_public_key + Hs(derivation, index) * G
bool derive_public_key_from_target_address(const account_public_address& destination_addr, const crypto::secret_key& tx_sec_key, size_t index, crypto::public_key& out_eph_public_key, crypto::key_derivation& derivation)
@ -1554,7 +1578,6 @@ namespace currency
ftp.tx_outs_attr = tx_outs_attr;
ftp.shuffle = shuffle;
ftp.flags = flags;
ftp.tx_version;
finalized_tx ft = AUTO_VAL_INIT(ft);
ft.tx = tx;
@ -1685,6 +1708,13 @@ namespace currency
return true;
}
crypto::hash get_asset_id_from_descriptor(const asset_descriptor_base& adb)
{
return get_hash_from_POD_objects(CRYPTO_HDS_ASSET_ID, adb.owner);
}
bool construct_tx(const account_keys& sender_account_keys, const finalize_tx_param& ftp, finalized_tx& result)
{
const std::vector<tx_source_entry>& sources = ftp.sources;
@ -1705,8 +1735,6 @@ namespace currency
result.ftp = ftp;
CHECK_AND_ASSERT_MES(destinations.size() <= CURRENCY_TX_MAX_ALLOWED_OUTS, false, "Too many outs (" << destinations.size() << ")! Tx can't be constructed.");
bool watch_only_mode = sender_account_keys.spend_secret_key == null_skey;
bool append_mode = false;
if (flags&TX_FLAG_SIGNATURE_MODE_SEPARATE && tx.vin.size())
append_mode = true;
@ -1768,10 +1796,23 @@ namespace currency
tx.extra.insert(tx.extra.end(), extra_local.begin(), extra_local.end());
}
// //first: separate zarcanum inputs and regular one
//std::vector<const tx_source_entry*> zc_sources;
//std::vector<const tx_source_entry*> NLSAG_sources;
uint64_t summary_inputs_money = 0;
crypto::hash asset_id_for_destinations = currency::null_hash;
asset_descriptor_operation* pado = nullptr;
if (tx.version > TRANSACTION_VERSION_PRE_HF4)
{
pado = get_type_in_variant_container<asset_descriptor_operation>(tx.extra);
if (pado)
{
crypto::secret_key stub = AUTO_VAL_INIT(stub);
bool r = derive_key_pair_from_key_pair(sender_account_keys.account_address.spend_public_key, one_time_secret_key, stub, pado->descriptor.owner, CRYPTO_HDS_ASSET_CONTROL_KEY);
CHECK_AND_ASSERT_MES(r, false, "Failed to derive_public_key_from_tx_and_account_pub_key()");
//also assign this asset id to destinations
asset_id_for_destinations = get_asset_id_from_descriptor(pado->descriptor);
}
}
std::vector<input_generation_context_data> in_contexts;
@ -1782,12 +1823,12 @@ namespace currency
size_t current_index = 0;
inputs_mapping.resize(sources.size());
size_t input_starter_index = tx.vin.size();
uint64_t summary_inputs_money = 0;
bool has_zc_inputs = false;
//fill inputs NLSAG and Zarcanum
for (const tx_source_entry& src_entr : sources)
{
inputs_mapping[current_index] = current_index++;
inputs_mapping[current_index] = current_index;
current_index++;
in_contexts.push_back(input_generation_context_data());
if(src_entr.is_multisig())
{//multisig input
@ -1901,9 +1942,27 @@ namespace currency
{
tx.vin.push_back(ins_zc);
}*/
uint64_t amount_of_assets = 0;
std::vector<tx_destination_entry> shuffled_dsts(destinations);
if (asset_id_for_destinations != currency::null_hash)
{
//must be asset publication
for (auto& item : shuffled_dsts)
{
if (item.asset_id == currency::ffff_hash)
{
item.asset_id = asset_id_for_destinations;
amount_of_assets += item.amount;
}
}
CHECK_AND_ASSERT_MES(pado, false, "pado is null ??");
pado->descriptor.current_supply = amount_of_assets;
//TODO: temporary
summary_inputs_money += amount_of_assets;
}
// "Shuffle" outs
std::vector<tx_destination_entry> shuffled_dsts(destinations);
if (shuffle)
std::sort(shuffled_dsts.begin(), shuffled_dsts.end(), [](const tx_destination_entry& de1, const tx_destination_entry& de2) { return de1.amount < de2.amount; });
@ -1984,7 +2043,7 @@ namespace currency
if (!has_zc_inputs)
{
r = generate_tx_balance_proof(tx, blinding_masks_sum);
r = generate_tx_balance_proof(tx, blinding_masks_sum, amount_of_assets);
CHECK_AND_ASSERT_MES(r, false, "generate_tx_balance_proof failed");
}
}
@ -2010,8 +2069,6 @@ namespace currency
if (tx.attachment.size())
add_attachments_info_to_extra(tx.extra, tx.attachment);
}
//
// generate ring signatures
//
@ -2021,10 +2078,12 @@ namespace currency
//size_t in_context_index = 0;
crypto::scalar_t local_blinding_masks_sum = 0; // ZC only
r = false;
for (size_t i = 0; i != sources.size(); i++)
for (size_t i_ = 0; i_ != sources.size(); i_++)
{
const tx_source_entry& source_entry = sources[inputs_mapping[i]];
crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, i + input_starter_index, tx_prefix_hash);
size_t i_mapped = inputs_mapping[i_];
const tx_source_entry& source_entry = sources[i_mapped];
crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, i_ + input_starter_index, tx_prefix_hash);
CHECK_AND_ASSERT_MES(tx_hash_for_signature != null_hash, false, "prepare_prefix_hash_for_sign failed");
std::stringstream ss_ring_s;
@ -2032,14 +2091,14 @@ namespace currency
{
// ZC
// blinding_masks_sum is supposed to be sum(mask of all tx output) - sum(masks of all pseudo out commitments)
r = generate_ZC_sig(tx_hash_for_signature, i + input_starter_index, source_entry, in_contexts[i], sender_account_keys, blinding_masks_sum, flags,
local_blinding_masks_sum, tx, i + 1 == sources.size());
r = generate_ZC_sig(tx_hash_for_signature, i_ + input_starter_index, source_entry, in_contexts[i_mapped], sender_account_keys, blinding_masks_sum, flags,
local_blinding_masks_sum, tx, i_ + 1 == sources.size());
CHECK_AND_ASSERT_MES(r, false, "generate_ZC_sigs failed");
}
else
{
// NLSAG
r = generate_NLSAG_sig(tx_hash_for_signature, tx_prefix_hash, i + input_starter_index, source_entry, sender_account_keys, in_contexts[i], txkey, flags, tx, &ss_ring_s);
r = generate_NLSAG_sig(tx_hash_for_signature, tx_prefix_hash, i_ + input_starter_index, source_entry, sender_account_keys, in_contexts[i_mapped], txkey, flags, tx, &ss_ring_s);
CHECK_AND_ASSERT_MES(r, false, "generate_NLSAG_sig failed");
}
@ -3324,6 +3383,12 @@ namespace currency
tv.type = "zc_balance_proof";
return true;
}
template<typename t_type>
bool operator()(const t_type& t_t)
{
tv.type = typeid(t_t).name();
return true;
}
};
//------------------------------------------------------------------
template<class t_container>

View file

@ -71,6 +71,7 @@ namespace currency
extra_alias_entry m_alias;
std::string m_user_data_blob;
extra_attachment_info m_attachment_info;
asset_descriptor_operation m_asset_operation;
};
//---------------------------------------------------------------------------------------------------------------
@ -289,6 +290,7 @@ namespace currency
uint64_t get_tx_version(uint64_t h, const hard_forks_descriptor& hfd);
bool construct_tx(const account_keys& sender_account_keys, const finalize_tx_param& param, finalized_tx& result);
crypto::hash get_asset_id_from_descriptor(const asset_descriptor_base& adb);
bool sign_multisig_input_in_tx(currency::transaction& tx, size_t ms_input_index, const currency::account_keys& keys, const currency::transaction& source_tx, bool *p_is_input_fully_signed = nullptr);
@ -316,6 +318,8 @@ namespace currency
bool generate_key_image_helper(const account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki);
bool derive_public_key_from_target_address(const account_public_address& destination_addr, const crypto::secret_key& tx_sec_key, size_t index, crypto::public_key& out_eph_public_key, crypto::key_derivation& derivation);
bool derive_public_key_from_target_address(const account_public_address& destination_addr, const crypto::secret_key& tx_sec_key, size_t index, crypto::public_key& out_eph_public_key);
bool derive_key_pair_from_key_pair(const crypto::public_key& src_pub_key, const crypto::secret_key& src_sec_key, crypto::secret_key& derived_sec_key, crypto::public_key& derived_pub_key, const char(&hs_domain)[32], uint64_t index = 0);
std::string short_hash_str(const crypto::hash& h);
bool is_mixattr_applicable_for_fake_outs_counter(uint8_t mix_attr, uint64_t fake_attr_count);
bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t current_blockchain_size, uint64_t current_time);
@ -537,6 +541,13 @@ namespace currency
return print_fixed_decimal_point(amount, CURRENCY_DISPLAY_DECIMAL_POINT);
}
//---------------------------------------------------------------
template<typename t_number>
std::string print_asset_money(t_number amount, size_t decimal_point)
{
return print_fixed_decimal_point(amount, decimal_point);
}
//---------------------------------------------------------------
template<class alias_rpc_details_t>
bool alias_rpc_details_to_alias_info(const alias_rpc_details_t& ard, currency::extra_alias_entry& ai)
{

View file

@ -91,22 +91,46 @@ namespace currency
++result;
}
return result;
}
}
//---------------------------------------------------------------
template<typename specific_type_t, typename variant_t_container>
bool get_type_in_variant_container(variant_t_container& av, specific_type_t& a)
specific_type_t* get_type_in_variant_container(variant_t_container& av)
{
for (auto& ai : av)
{
if (ai.type() == typeid(specific_type_t))
{
a = boost::get<specific_type_t>(ai);
return true;
return &boost::get<specific_type_t>(ai);
}
}
return nullptr;
}
//---------------------------------------------------------------
template<typename specific_type_t, typename variant_t_container>
bool get_type_in_variant_container(variant_t_container& av, specific_type_t& a)
{
const specific_type_t* pa = get_type_in_variant_container<const specific_type_t>(av);
if (pa)
{
a = *pa;
return true;
}
return false;
}
//---------------------------------------------------------------
//---------------------------------------------------------------
template<typename specific_type_t, typename variant_t_container>
specific_type_t& get_type_in_variant_container_by_ref(variant_t_container& av)
{
for (auto& ai : av)
{
if (ai.type() == typeid(specific_type_t))
{
return boost::get<specific_type_t>(ai);
}
}
ASSERT_MES_AND_THROW("Objec not found");
}
// if cb returns true, it means "continue", false -- means "stop"
template<typename specific_type_t, typename variant_container_t, typename callback_t>
bool process_type_in_variant_container(const variant_container_t& av, callback_t& cb, bool return_value_if_none_found = true)
@ -194,6 +218,7 @@ namespace currency
catch(...)
{
// should never go here, just precaution
return false;
}
return false;
@ -423,6 +448,26 @@ namespace currency
size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size);
inline
void put_t_to_buff(std::string& buff)
{}
template <typename T, typename... Types>
void put_t_to_buff(std::string& buff, const T& var1, Types&... var2)
{
static_assert(std::is_pod<T>::value, "T must be a POD type.");
buff.append((const char*)&var1, sizeof(var1));
put_t_to_buff(buff, var2...);
}
template <typename... Types>
crypto::hash get_hash_from_POD_objects(Types&... var1)
{
std::string buff;
put_t_to_buff(buff, var1...);
return crypto::cn_fast_hash(buff.data(), buff.size());
}
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \
CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \

View file

@ -100,8 +100,11 @@ namespace currency
tx_destination_entry() = default;
tx_destination_entry(uint64_t a, const account_public_address& ad) : amount(a), addr(1, ad) {}
tx_destination_entry(uint64_t a, const account_public_address& ad, const crypto::hash& aid) : amount(a), addr(1, ad), asset_id(aid) {}
tx_destination_entry(uint64_t a, const account_public_address& ad, uint64_t ut) : amount(a), addr(1, ad), unlock_time(ut) {}
tx_destination_entry(uint64_t a, const std::list<account_public_address>& addr) : amount(a), addr(addr), minimum_sigs(addr.size()) {}
tx_destination_entry(uint64_t a, const std::list<account_public_address>& addr) : amount(a), addr(addr), minimum_sigs(addr.size()){}
tx_destination_entry(uint64_t a, const std::list<account_public_address>& addr, const crypto::hash& aid) : amount(a), addr(addr), minimum_sigs(addr.size()), asset_id(aid) {}
BEGIN_SERIALIZE_OBJECT()
FIELD(amount)
@ -110,6 +113,7 @@ namespace currency
FIELD(amount_to_provide)
FIELD(unlock_time)
FIELD(htlc_options)
FIELD(asset_id)
END_SERIALIZE()
};

View file

@ -17,6 +17,7 @@
#define CORE_EVENT_ADD_ALIAS "CORE_EVENT_ADD_ALIAS"
#define CORE_EVENT_UPDATE_ALIAS "CORE_EVENT_UPDATE_ALIAS"
#define CORE_EVENT_BLOCK_ADDED "CORE_EVENT_BLOCK_ADDED"
#define CORE_EVENT_ADD_ASSET "CORE_EVENT_ADD_ASSET"
namespace currency

View file

@ -19,9 +19,9 @@ namespace bc_services
{
//fields filled in UI
uint8_t offer_type; // OFFER_TYPE_PRIMARY_TO_TARGET(SELL ORDER) - 0, OFFER_TYPE_TARGET_TO_PRIMARY(BUY ORDER) - 1 etc.
uint64_t amount_primary; // amount of the currency
uint64_t amount_target; // amount of other currency or goods
uint8_t offer_type = 0; // OFFER_TYPE_PRIMARY_TO_TARGET(SELL ORDER) - 0, OFFER_TYPE_TARGET_TO_PRIMARY(BUY ORDER) - 1 etc.
uint64_t amount_primary = 0; // amount of the currency
uint64_t amount_target = 0; // amount of other currency or goods
std::string bonus; //
std::string target; // [] currency / goods
std::string primary; // currency for goods
@ -33,7 +33,7 @@ namespace bc_services
std::string deal_option; // []full amount, by parts
std::string category; // []
std::string preview_url; // []
uint8_t expiration_time; // n-days
uint8_t expiration_time = 0; // n-days
//-----------------
BEGIN_KV_SERIALIZE_MAP()

View file

@ -61,7 +61,7 @@ inline bool do_serialize(Archive &ar, T &v)
#define VARIANT_TAG(A, T, Tg) \
template <bool W> struct variant_serialization_traits<A<W>, T> { static inline typename A<W>::variant_tag_type get_tag() { return Tg; } }
#define BEGIN_SERIALIZE() \
template <bool W, template <bool> class Archive> bool do_serialize(Archive<W> &_ser_ar) {
template <bool W, template <bool> class Archive> bool do_serialize(Archive<W> &_ser_ar) {uint8_t s_current_version ATTRIBUTE_UNUSED = 0; uint8_t s_version ATTRIBUTE_UNUSED = 0;
#define BEGIN_SERIALIZE_OBJECT() \
template <bool W, template <bool> class Archive> bool do_serialize(Archive<W> &_ser_ar) { _ser_ar.begin_object(); bool _ser_res = do_serialize_object(_ser_ar); _ser_ar.end_object(); return _ser_res; } \
template <bool W, template <bool> class Archive> bool do_serialize_object(Archive<W> &_ser_ar){
@ -98,6 +98,28 @@ do { \
if (!_ser_ar.stream().good()) return false; \
} while (0);
#define VERSION() \
do { \
_ser_ar.tag("VERSION"); \
if (!_ser_ar.stream().good()){break;} \
_ser_ar.serialize_varint(s_version); \
if (!_ser_ar.stream().good()) return false; \
if(s_version > s_current_version) return false; \
} while (0);
#define CURRENT_VERSION(v) \
do { \
s_current_version = v; \
if (_ser_ar.is_saving_arch()) { s_version = v; } \
} while (0);
#define BEGIN_VERSIONED_SERIALIZE() \
BEGIN_SERIALIZE() \
VERSION()
#define DEFINE_SERIALIZATION_VERSION(v) inline static uint32_t get_serialization_version() { return v; }

View file

@ -752,6 +752,49 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
}
}
if (ptc.tx_money_spent_in_ins)
{
//check if there are asset_registration that belong to this wallet
asset_descriptor_operation ado = AUTO_VAL_INIT(ado);
if (get_type_in_variant_container(tx.extra, ado))
{
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER)
{
crypto::public_key self_check = AUTO_VAL_INIT(self_check);
crypto::secret_key asset_control_key = AUTO_VAL_INIT(asset_control_key);
bool r = derive_key_pair_from_key_pair(tx_pub_key, m_account.get_keys().spend_secret_key, asset_control_key, self_check, CRYPTO_HDS_ASSET_CONTROL_KEY);
if (!r)
{
//not critical error, continue to work
LOG_ERROR("Failed to derive_key_pair_from_key_pair for asset_descriptor_operation in tx " << get_transaction_hash(tx));
}else
{
if (self_check != ado.descriptor.owner)
{
//still not critical error
LOG_ERROR("Public key from asset_descriptor_operation(" << ado.descriptor.owner << ") not much with derived public key(" << self_check << "), for tx" << get_transaction_hash(tx));
}
else
{
wallet_own_asset_context& asset_context = m_own_asset_descriptors[get_hash_from_POD_objects(CRYPTO_HDS_ASSET_ID, ado.descriptor.owner)];
asset_context.asset_descriptor = ado.descriptor;
asset_context.height = height;
std::stringstream ss;
ss << "New Asset Registered:"
<< ENDL << "Name: " << asset_context.asset_descriptor.full_name
<< ENDL << "Ticker: " << asset_context.asset_descriptor.ticker
<< ENDL << "Total Max Supply: " << print_asset_money(asset_context.asset_descriptor.total_max_supply, asset_context.asset_descriptor.decimal_point)
<< ENDL << "Current Supply: " << print_asset_money(asset_context.asset_descriptor.current_supply, asset_context.asset_descriptor.decimal_point)
<< ENDL << "DecimalPoint: " << asset_context.asset_descriptor.decimal_point;
WLT_LOG_MAGENTA(ss.str(), LOG_LEVEL_0);
if (m_wcallback)
m_wcallback->on_message(i_wallet2_callback::ms_yellow, ss.str());
}
}
}
}
}
if (ptc.tx_money_spent_in_ins)
{//this actually is transfer transaction, notify about spend
@ -1834,7 +1877,7 @@ detail::split_strategy_id_t wallet2::get_current_split_strategy()
return tools::detail::ssi_void;
}
//
void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx)
void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx, const crypto::hash& asset_id)
{
std::vector<currency::extra_v> extra;
std::vector<currency::attachment_v> attachments;
@ -1843,13 +1886,14 @@ void wallet2::transfer(uint64_t amount, const currency::account_public_address&
dst.resize(1);
dst.back().addr.push_back(acc);
dst.back().amount = amount;
dst.back().asset_id = asset_id;
this->transfer(dst, 0, 0, TX_DEFAULT_FEE, extra, attachments, get_current_split_strategy(), tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD), result_tx);
}
//----------------------------------------------------------------------------------------------------
void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc)
void wallet2::transfer(uint64_t amount, const currency::account_public_address& acc, const crypto::hash& asset_id)
{
transaction result_tx = AUTO_VAL_INIT(result_tx);
this->transfer(amount, acc, result_tx);
this->transfer(amount, acc, result_tx, asset_id);
}
//----------------------------------------------------------------------------------------------------
void wallet2::reset_creation_time(uint64_t timestamp)
@ -2507,6 +2551,15 @@ void wallet2::detach_blockchain(uint64_t including_height)
++it;
}
//asset descriptors
for (auto it = m_own_asset_descriptors.begin(); it != m_own_asset_descriptors.end(); )
{
if (including_height <= it->second.height)
it = m_own_asset_descriptors.erase(it);
else
++it;
}
WLT_LOG_L0("Detached blockchain on height " << including_height << ", transfers detached " << transfers_detached << ", blocks detached " << blocks_detached);
}
//----------------------------------------------------------------------------------------------------
@ -4122,6 +4175,25 @@ void wallet2::request_alias_registration(currency::extra_alias_entry& ai, curren
transfer(destinations, 0, 0, fee, extra, attachments, get_current_split_strategy(), tx_dust_policy(DEFAULT_DUST_THRESHOLD), res_tx, CURRENCY_TO_KEY_OUT_RELAXED, false);
}
//----------------------------------------------------------------------------------------------------
void wallet2::publish_new_asset(const currency::asset_descriptor_base& asset_info, const std::vector<currency::tx_destination_entry>& destinations, currency::transaction& result_tx, crypto::hash& asset_id)
{
asset_descriptor_operation asset_reg_info = AUTO_VAL_INIT(asset_reg_info);
asset_reg_info.descriptor = asset_info;
asset_reg_info.operation_type = ASSET_DESCRIPTOR_OPERATION_REGISTER;
construct_tx_param ctp = get_default_construct_tx_param();
ctp.dsts = destinations;
ctp.extra.push_back(asset_reg_info);
finalized_tx ft = AUTO_VAL_INIT(ft);
this->transfer(ctp, ft, true, nullptr);
result_tx = ft.tx;
//get generated asset id
currency::asset_descriptor_operation ado = AUTO_VAL_INIT(ado);
bool r = get_type_in_variant_container(result_tx.extra, ado);
CHECK_AND_ASSERT_THROW_MES(r, "Failed find asset info in tx");
asset_id = get_asset_id_from_descriptor(ado.descriptor);
}
//----------------------------------------------------------------------------------------------------
void wallet2::request_alias_update(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward)
{
if (!validate_alias_name(ai.m_alias))
@ -4930,6 +5002,9 @@ assets_selection_context wallet2::get_needed_money(uint64_t fee, const std::vect
amounts_map[currency::null_hash].needed_amount = fee;
for(auto& dt : dsts)
{
if(dt.asset_id == currency::ffff_hash)
continue; //this destination for emmition only
THROW_IF_TRUE_WALLET_EX(0 == dt.amount, error::zero_destination);
uint64_t money_to_add = dt.amount;
if (dt.amount_to_provide)
@ -5591,22 +5666,20 @@ void wallet2::prepare_tx_destinations(uint64_t needed_money,
change_dts.asset_id = asset_id;
}
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(found_money >= needed_money, "needed_money==" << needed_money << " < found_money==" << found_money);
if (asset_id != currency::null_hash)
{
if (change_dts.amount)
{
final_detinations.push_back(change_dts);
}
return;
}
uint64_t dust = 0;
bool r = detail::apply_split_strategy_by_id(destination_split_strategy_id, dsts, change_dts, dust_policy.dust_threshold, final_detinations, dust, WALLET_MAX_ALLOWED_OUTPUT_AMOUNT);
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(r, "invalid split strategy id: " << destination_split_strategy_id);
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(dust_policy.dust_threshold >= dust, "invalid dust value: dust = " << dust << ", dust_threshold = " << dust_policy.dust_threshold);
//@#@
#ifdef _DEBUG
if (final_detinations.size() > 10)
{
WLT_LOG_L0("final_detinations.size()=" << final_detinations.size());
}
#endif
//@#@
if (0 != dust && !dust_policy.add_to_fee)
{
final_detinations.push_back(currency::tx_destination_entry(dust, dust_policy.addr_for_dust));
@ -5666,6 +5739,7 @@ void wallet2::prepare_transaction(construct_tx_param& ctp, currency::finalize_tx
prepare_tx_destinations(needed_money_map, static_cast<detail::split_strategy_id_t>(ctp.split_strategy_id), ctp.dust_policy, ctp.dsts, ftp.prepared_destinations);
TIME_MEASURE_FINISH_MS(prepare_tx_destinations_time);
if (ctp.mark_tx_as_complete && !ftp.sources.empty())
ftp.sources.back().separately_signed_tx_complete = true;
@ -5806,10 +5880,9 @@ construct_tx_param wallet2::get_default_construct_tx_param_inital()
ctp.shuffle = 0;
return ctp;
}
const construct_tx_param& wallet2::get_default_construct_tx_param()
construct_tx_param wallet2::get_default_construct_tx_param()
{
static construct_tx_param ctp = get_default_construct_tx_param_inital();
return ctp;
return get_default_construct_tx_param_inital();
}
//----------------------------------------------------------------------------------------------------
bool wallet2::store_unsigned_tx_to_file_and_reserve_transfers(const currency::finalize_tx_param& ftp, const std::string& filename, std::string* p_unsigned_tx_blob_str /* = nullptr */)

View file

@ -184,8 +184,8 @@ namespace tools
else
{
currency::decompose_amount_into_digits(de.amount, dust_threshold,
[&](uint64_t chunk) { splitted_dsts.push_back(currency::tx_destination_entry(chunk, de.addr)); },
[&](uint64_t a_dust) { splitted_dsts.push_back(currency::tx_destination_entry(a_dust, de.addr)); }, max_output_allowed);
[&](uint64_t chunk) { splitted_dsts.push_back(currency::tx_destination_entry(chunk, de.addr, de.asset_id)); },
[&](uint64_t a_dust) { splitted_dsts.push_back(currency::tx_destination_entry(a_dust, de.addr, de.asset_id)); }, max_output_allowed);
}
}
@ -241,7 +241,7 @@ namespace tools
const currency::tx_destination_entry& change_dst, uint64_t dust_threshold,
std::vector<currency::tx_destination_entry>& splitted_dsts, uint64_t& dust, uint64_t max_output_allowed)
{
splitted_dsts = dsts;
splitted_dsts.insert(splitted_dsts.end(), dsts.begin(), dsts.end());
if (change_dst.amount > 0)
splitted_dsts.push_back(change_dst);
}
@ -252,6 +252,9 @@ namespace tools
const currency::tx_destination_entry& change_dst, uint64_t dust_threshold,
std::vector<currency::tx_destination_entry>& splitted_dsts, uint64_t& dust, uint64_t max_output_allowed)
{
//&&&&&
LOG_PRINT_MAGENTA("[--apply_split_strategy_by_id, split strtegy_id: " << id, LOG_LEVEL_0);
switch (id)
{
case ssi_digit:
@ -506,6 +509,19 @@ namespace tools
};
struct wallet_own_asset_context
{
currency::asset_descriptor_base asset_descriptor;
crypto::secret_key control_key;
uint64_t height = 0;
BEGIN_BOOST_SERIALIZATION()
BOOST_SERIALIZE(asset_descriptor)
BOOST_SERIALIZE(control_key)
BOOST_SERIALIZE(height)
END_BOOST_SERIALIZATION()
};
void assign_account(const currency::account_base& acc);
void generate(const std::wstring& path, const std::string& password, bool auditable_wallet);
void restore(const std::wstring& path, const std::string& pass, const std::string& seed_or_tracking_seed, bool tracking_wallet, const std::string& seed_password);
@ -551,7 +567,8 @@ namespace tools
void request_alias_registration(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward, const crypto::secret_key& authority_key = currency::null_skey);
void request_alias_update(currency::extra_alias_entry& ai, currency::transaction& res_tx, uint64_t fee, uint64_t reward);
bool check_available_sources(std::list<uint64_t>& amounts);
void publish_new_asset(const currency::asset_descriptor_base& asset_info, const std::vector<currency::tx_destination_entry>& destinations, currency::transaction& result_tx, crypto::hash& asset_id);
bool set_core_proxy(const std::shared_ptr<i_core_proxy>& proxy);
void set_pos_mint_packing_size(uint64_t new_size);
@ -564,8 +581,8 @@ namespace tools
uint64_t unlocked_balance() const;
void transfer(uint64_t amount, const currency::account_public_address& acc);
void transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx);
void transfer(uint64_t amount, const currency::account_public_address& acc, const crypto::hash& asset_id = currency::null_hash);
void transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx, const crypto::hash& asset_id = currency::null_hash);
void transfer(const std::vector<currency::tx_destination_entry>& dsts,
size_t fake_outputs_count,
@ -803,6 +820,10 @@ namespace tools
a & m_active_htlcs;
a & m_active_htlcs_txid;
if (ver < 154)
return;
a & m_own_asset_descriptors;
}
void wipeout_extra_if_needed(std::vector<wallet_public::wallet_transfer_info>& transfer_history);
@ -985,7 +1006,7 @@ private:
template<typename input_t>
bool process_input_t(const input_t& in_t, wallet2::process_transaction_context& ptc, const currency::transaction& tx);
const construct_tx_param& get_default_construct_tx_param();
construct_tx_param get_default_construct_tx_param();
uint64_t get_tx_expiration_median() const;
@ -1080,6 +1101,7 @@ private:
std::unordered_map<crypto::hash, tools::wallet_public::wallet_transfer_info> m_unconfirmed_txs;
std::unordered_set<crypto::hash> m_unconfirmed_multisig_transfers;
std::unordered_map<crypto::hash, crypto::secret_key> m_tx_keys;
std::unordered_map<crypto::hash, wallet_own_asset_context> m_own_asset_descriptors;
std::multimap<uint64_t, htlc_expiration_trigger> m_htlcs; //map [expired_if_more_then] -> height of expiration
amount_gindex_to_transfer_id_container m_active_htlcs; // map [amount; gindex] -> transfer index
@ -1111,6 +1133,7 @@ private:
} // namespace tools
BOOST_CLASS_VERSION(tools::wallet2, WALLET_FILE_SERIALIZATION_VERSION)
BOOST_CLASS_VERSION(tools::wallet_public::wallet_transfer_info, 11)
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 3)
BOOST_CLASS_VERSION(tools::wallet2::transfer_details_base, 2)
@ -1288,7 +1311,7 @@ namespace tools
ptc.is_derived_from_coinbase = true;
else
ptc.is_derived_from_coinbase = false;
WLT_LOG_L0("Spent key out, transfer #" << tr_index << ", amount: " << print_money(td.amount()) << ", with tx: " << get_transaction_hash(tx) << ", at height " << ptc.height <<
WLT_LOG_L0("Spent key out, transfer #" << tr_index << ", amount: " << currency::print_money(td.amount()) << ", with tx: " << get_transaction_hash(tx) << ", at height " << ptc.height <<
"; flags: " << flags_before << " -> " << td.m_flags);
ptc.mtd.spent_indices.push_back(ptc.i);
remove_transfer_from_expiration_list(tr_index);

View file

@ -463,6 +463,7 @@ namespace tools
ss << currency::get_account_address_as_str(a) << ";";
}
ss << " anount: " << currency::print_money(dst.amount);
ss << " asset_id: " << dst.asset_id;
}
ss << "\nunlock_time: " << m_unlock_time;
@ -757,4 +758,5 @@ if (cond)
ss << mess; \
LOG_ERROR("THROW EXCEPTION: wallet_common_error"); \
tools::error::throw_wallet_ex<tools::error::wallet_common_error>(std::string(__FILE__ ":" STRINGIZE(__LINE__)), ss.str()); \
}
}

View file

@ -1001,7 +1001,6 @@ bool init_output_indices(map_output_idx_t& outs, map_output_t& outs_mine, const
{
for (const block& blk : blockchain)
{
volatile uint64_t height = get_block_height(blk);
std::vector<const transaction*> vtx;
vtx.push_back(&blk.miner_tx);

View file

@ -912,7 +912,7 @@ int main(int argc, char* argv[])
// GENERATE_AND_PLAY(pos_wallet_minting_same_amount_diff_outs); // Long test! Takes ~10 hours to simulate 6000 blocks on 2015 middle-end computer
//GENERATE_AND_PLAY(pos_emission_test); // Long test! by demand only
GENERATE_AND_PLAY(pos_wallet_big_block_test);
GENERATE_AND_PLAY(block_template_against_txs_size);
//GENERATE_AND_PLAY(block_template_against_txs_size); // Long test! by demand only
GENERATE_AND_PLAY(pos_altblocks_validation);
// alternative blocks and generic chain-switching tests
@ -1060,6 +1060,14 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(isolate_auditable_and_proof);
GENERATE_AND_PLAY(zarcanum_basic_test);
//stop_on_first_fail = true;
//for (size_t i = 0; i != 100; i++)
//{
multiassets_basic_test::ts_starter = 0;
GENERATE_AND_PLAY(multiassets_basic_test);
//}
// GENERATE_AND_PLAY(gen_block_reward);

View file

@ -1,5 +1,4 @@
// Copyright (c) 2022 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include "chaingen.h"

View file

@ -41,3 +41,4 @@
#include "atomic_tests.h"
#include "isolate_auditable_and_proof.h"
#include "zarcanum_test.h"
#include "multiassets_test.h"

View file

@ -927,7 +927,7 @@ bool gen_checkpoints_set_after_switching_to_altchain::generate(std::vector<test_
// \
// \- (2 )- <- main chain
bool r = false;
//bool r = false;
GENERATE_ACCOUNT(miner_acc);
GENERATE_ACCOUNT(alice_acc);
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time());

View file

@ -3135,7 +3135,7 @@ bool escrow_balance::generate(std::vector<test_event_entry>& events) const
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
m_alice_bob_start_amount = MK_TEST_COINS(200);
uint64_t amount_chunks = 10;
//uint64_t amount_chunks = 10;
m_alice_bob_start_chunk_amount = m_alice_bob_start_amount / 10;
transaction tx_0 = AUTO_VAL_INIT(tx_0);
@ -3159,7 +3159,7 @@ bool escrow_balance::generate(std::vector<test_event_entry>& events) const
bool escrow_balance::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
bool r = false, stub_bool = false;
bool r = false;
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]);

View file

@ -186,7 +186,7 @@ bool hard_fork_1_unlock_time_2_in_coinbase::generate(std::vector<test_event_entr
// Test idea: make sure etc_tx_details_unlock_time2 can be used in-coinbase txs
// only after hardfork 1
bool r = false;
//bool r = false;
GENERATE_ACCOUNT(miner_acc);
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time());
generator.set_hardfork_height(1, m_hardfork_height);
@ -257,7 +257,7 @@ bool hard_fork_1_chain_switch_pow_only::generate(std::vector<test_event_entry>&
{
// Test idea: make sure chain switches without PoS before and after hardfork
bool r = false;
//bool r = false;
GENERATE_ACCOUNT(miner_acc);
GENERATE_ACCOUNT(alice_acc);
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time());

View file

@ -76,7 +76,7 @@ bool hard_fork_2_tx_payer_in_wallet::generate(std::vector<test_event_entry>& eve
bool hard_fork_2_tx_payer_in_wallet::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
bool r = false, stub_bool = false;
bool r = false;
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, m_accounts[MINER_ACC_IDX]);
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]);
@ -324,7 +324,7 @@ bool hard_fork_2_tx_receiver_in_wallet::generate(std::vector<test_event_entry>&
bool hard_fork_2_tx_receiver_in_wallet::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
bool r = false, stub_bool = false;
bool r = false;
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, m_accounts[MINER_ACC_IDX]);
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]);
@ -468,7 +468,7 @@ bool hard_fork_2_tx_extra_alias_entry_in_wallet::generate(std::vector<test_event
bool hard_fork_2_tx_extra_alias_entry_in_wallet::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
bool r = false, stub_bool = false;
bool r = false;
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]);
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, m_accounts[MINER_ACC_IDX]);
@ -670,7 +670,7 @@ bool hard_fork_2_auditable_addresses_basics::generate(std::vector<test_event_ent
bool hard_fork_2_auditable_addresses_basics::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
bool r = false, stub_bool = false;
bool r = false;
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]);
std::shared_ptr<tools::wallet2> bob_wlt = init_playtime_test_wallet(events, c, m_accounts[BOB_ACC_IDX]);
@ -909,7 +909,7 @@ bool hard_fork_2_awo_wallets_basic_test<before_hf_2>::c1(currency::core& c, size
static const std::wstring bob_wo_restored_filename(L"bob_wo_restored_wallet");
static const std::wstring bob_non_auditable_filename(L"bob_non_auditable_wallet");
bool r = false, stub_bool = false;
bool r = false;
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX);
@ -1181,7 +1181,7 @@ bool hard_fork_2_alias_update_using_old_tx<before_hf_2>::generate(std::vector<te
template<bool before_hf_2>
bool hard_fork_2_alias_update_using_old_tx<before_hf_2>::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
bool r = false, stub_bool = false;
bool r = false;
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX);

View file

@ -0,0 +1,148 @@
// Copyright (c) 2014-2018 Zano Project
// Copyright (c) 2014-2018 The Louisdor Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "chaingen.h"
#include "multiassets_test.h"
#include "wallet_test_core_proxy.h"
#include "random_helper.h"
#define AMOUNT_TO_TRANSFER_MULTIASSETS_BASIC (TESTS_DEFAULT_FEE)
#define AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC 500000000000000000
using namespace currency;
uint64_t multiassets_basic_test::ts_starter = 0;
//------------------------------------------------------------------------------
multiassets_basic_test::multiassets_basic_test()
{
// TODO: remove the following line
LOG_PRINT_MAGENTA("STARTER TS: " << ts_starter, LOG_LEVEL_0);
random_state_test_restorer::reset_random(ts_starter);
REGISTER_CALLBACK_METHOD(multiassets_basic_test, configure_core);
REGISTER_CALLBACK_METHOD(multiassets_basic_test, c1);
m_hardforks.set_hardfork_height(1, 1);
m_hardforks.set_hardfork_height(2, 1);
m_hardforks.set_hardfork_height(3, 1);
m_hardforks.set_hardfork_height(4, 1);
}
bool multiassets_basic_test::generate(std::vector<test_event_entry>& events) const
{
m_accounts.resize(MINER_ACC_IDX+1);
account_base& miner_acc = m_accounts[MINER_ACC_IDX];
miner_acc.generate();
uint64_t ts = 145000000;
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks
set_hard_fork_heights_to_generator(generator);
//TODO: Need to make sure REWIND_BLOCKS_N and other coretests codebase are capable of following hardfork4 rules
//in this test hardfork4 moment moved to runtime section
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3);
DO_CALLBACK(events, "c1");
return true;
}
bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
bool r = false;
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX);
miner_wlt->get_account().set_createtime(0);
account_base alice_acc;
alice_acc.generate();
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, alice_acc);
alice_wlt->get_account().set_createtime(0);
miner_wlt->refresh();
asset_descriptor_base adb = AUTO_VAL_INIT(adb);
adb.total_max_supply = 1000000000000000000; //1M coins
adb.full_name = "Test coins";
adb.ticker = "TCT";
adb.decimal_point = 12;
std::vector<currency::tx_destination_entry> destinations(2);
destinations[0].addr.push_back(miner_wlt->get_account().get_public_address());
destinations[0].amount = AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC;
destinations[0].asset_id = currency::ffff_hash;
destinations[1].addr.push_back(alice_wlt->get_account().get_public_address());
destinations[1].amount = AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC;
destinations[1].asset_id = currency::ffff_hash;
LOG_PRINT_MAGENTA("destinations[0].asset_id:" << destinations[0].asset_id, LOG_LEVEL_0);
LOG_PRINT_MAGENTA("destinations[1].asset_id:" << destinations[1].asset_id, LOG_LEVEL_0);
LOG_PRINT_MAGENTA("currency::ffff_hash:" << currency::ffff_hash, LOG_LEVEL_0);
currency::transaction tx = AUTO_VAL_INIT(tx);
crypto::hash asset_id = currency::null_hash;
miner_wlt->publish_new_asset(adb, destinations, tx, asset_id);
LOG_PRINT_L0("Published new asset: " << asset_id << ", tx_id: " << currency::get_transaction_hash(tx));
//pass over hardfork
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
miner_wlt->refresh();
alice_wlt->refresh();
uint64_t mined = 0;
std::unordered_map<crypto::hash, tools::wallet_public::asset_balance_entry_base> balances;
miner_wlt->balance(balances, mined);
auto it_asset = balances.find(asset_id);
auto it_native = balances.find(currency::null_hash);
CHECK_AND_ASSERT_MES(it_asset != balances.end() && it_native != balances.end(), false, "Failed to find needed asset in result balances");
CHECK_AND_ASSERT_MES(it_asset->second.total == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC, false, "Failed to find needed asset in result balances");
CHECK_AND_ASSERT_MES(it_native->second.total == uint64_t(17517226)*COIN, false, "Failed to find needed asset in result balances");
balances.clear();
alice_wlt->balance(balances, mined);
it_asset = balances.find(asset_id);
it_native = balances.find(currency::null_hash);
CHECK_AND_ASSERT_MES(it_asset != balances.end(), false, "Failed to find needed asset in result balances");
CHECK_AND_ASSERT_MES(it_native == balances.end(), false, "Failed to find needed asset in result balances");
CHECK_AND_ASSERT_MES(it_asset->second.total == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC, false, "Failed to find needed asset in result balances");
miner_wlt->transfer(AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC/2, alice_wlt->get_account().get_public_address(), asset_id);
//pass over hardfork
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
alice_wlt->refresh();
balances.clear();
alice_wlt->balance(balances, mined);
it_asset = balances.find(asset_id);
CHECK_AND_ASSERT_MES(it_asset != balances.end(), false, "Failed to find needed asset in result balances");
CHECK_AND_ASSERT_MES(it_asset->second.total == AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC + AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC/2, false, "Failed to find needed asset in result balances");
try {
miner_wlt->transfer(AMOUNT_ASSETS_TO_TRANSFER_MULTIASSETS_BASIC / 2, alice_wlt->get_account().get_public_address(), asset_id);
//pass over hardfork
CHECK_AND_ASSERT_MES(false, false, "Transfer with 0 Zano worked(fail)");
}
catch (...)
{
return true;
}
return true;
}

View file

@ -0,0 +1,18 @@
// Copyright (c) 2014-2018 Zano Project
// Copyright (c) 2014-2018 The Louisdor Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include "chaingen.h"
#include "wallet_tests_basic.h"
struct multiassets_basic_test : public wallet_test
{
static uint64_t ts_starter;
multiassets_basic_test();
bool generate(std::vector<test_event_entry>& events) const;
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
};

View file

@ -3290,7 +3290,6 @@ bool wallet_unconfimed_tx_balance::generate(std::vector<test_event_entry>& event
bool wallet_unconfimed_tx_balance::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
bool r = false;
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX);
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_balance("", "Alice", alice_wlt, MK_TEST_COINS(100), false, UINT64_MAX, MK_TEST_COINS(100)), false, "");
@ -3505,7 +3504,6 @@ wallet_watch_only_and_chain_switch::wallet_watch_only_and_chain_switch()
bool wallet_watch_only_and_chain_switch::generate(std::vector<test_event_entry>& events) const
{
bool r = false;
m_accounts.resize(TOTAL_ACCS_COUNT);
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate();
@ -3602,7 +3600,6 @@ wallet_spend_form_auditable_and_track::wallet_spend_form_auditable_and_track()
bool wallet_spend_form_auditable_and_track::generate(std::vector<test_event_entry>& events) const
{
bool r = false;
m_accounts.resize(TOTAL_ACCS_COUNT);
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate();

View file

@ -86,7 +86,7 @@ bool zarcanum_basic_test::c1(currency::core& c, size_t ev_index, const std::vect
//miner_wlt->refresh();
alice_wlt->refresh();
uint64_t unlocked = 0;
//uint64_t unlocked = 0;
//uint64_t balance = alice_wlt->balance(unlocked);
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", transfer_amount * 4, UINT64_MAX, transfer_amount * 4), false, "");

View file

@ -0,0 +1,12 @@
// Copyright (c) 2012-2022 The Zano project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "gtest/gtest.h"
//#include "common/util.h"
//#include "p2p/net_peerlist.h"
//#include "core_tests/chaingen.h"
//TODO

View file

@ -740,3 +740,166 @@ TEST(Serialization, serializes_transacion_versions)
validate_tx_serialisation(tx);
}
struct A
{
std::string one;
std::string two;
std::vector<std::string> vector_one;
BEGIN_SERIALIZE()
FIELD(one)
FIELD(two)
FIELD(vector_one)
END_SERIALIZE()
};
struct A_v1 : public A
{
std::vector<std::string> vector_two;
BEGIN_SERIALIZE()
CURRENT_VERSION(1)
FIELD(one)
FIELD(two)
FIELD(vector_one)
VERSION()
if (s_version < 1) return true;
FIELD(vector_two)
END_SERIALIZE()
};
struct A_v2 : public A_v1
{
std::vector<std::string> vector_3;
std::vector<std::string> vector_4;
BEGIN_SERIALIZE()
CURRENT_VERSION(2)
FIELD(one)
FIELD(two)
FIELD(vector_one)
VERSION()
if (s_version < 1) return true;
FIELD(vector_two)
if (s_version < 2) return true;
FIELD(vector_3)
FIELD(vector_4)
END_SERIALIZE()
};
struct A_v3 : public A_v2
{
std::vector<std::string> vector_5;
BEGIN_SERIALIZE()
CURRENT_VERSION(3)
FIELD(one)
FIELD(two)
FIELD(vector_one)
VERSION()
if (s_version < 1) return true;
FIELD(vector_two)
if (s_version < 2) return true;
FIELD(vector_3)
FIELD(vector_4)
if (s_version < 3) return true;
FIELD(vector_5)
END_SERIALIZE()
};
inline bool operator==(const A& lhs, const A& rhs)
{
if ((lhs.one != rhs.one || lhs.two != rhs.two || lhs.vector_one != rhs.vector_one))
{
return false;
}
return true;
}
inline bool operator==(const A_v1& lhs, const A_v1& rhs)
{
if (!(static_cast<const A&>(lhs) == static_cast<const A&>(rhs)))
return false;
if ((lhs.vector_two != rhs.vector_two))
{
return false;
}
return true;
}
inline bool operator==(const A_v2& lhs, const A_v2& rhs)
{
if (!(static_cast<const A_v1&>(lhs) == static_cast<const A_v1&>(rhs)))
return false;
if ((lhs.vector_3 != rhs.vector_3))
{
return false;
}
return true;
}
inline bool operator==(const A_v3& lhs, const A_v3& rhs)
{
if (!(static_cast<const A_v2&>(lhs) == static_cast<const A_v2&>(rhs)))
return false;
if ((lhs.vector_5 != rhs.vector_5))
{
return false;
}
return true;
}
template<typename first, typename second>
bool perform_test_ser_vers(second& f)
{
string blob;
first s_s = AUTO_VAL_INIT(s_s);
if (!serialization::dump_binary(f, blob))
return false;
if (!serialization::parse_binary(blob, s_s))
return false;
if (!(f == static_cast<second&>(s_s)))
{
return false;
}
return true;
}
TEST(Serialization, versioning2)
{
A_v3 a_3;
a_3.one = "one";
a_3.two = "two";
a_3.vector_one.push_back(a_3.one);
a_3.vector_one.push_back(a_3.two);
a_3.vector_two = a_3.vector_one;
a_3.vector_5 = a_3.vector_4 = a_3.vector_3 = a_3.vector_two;
A_v2 a_2(a_3);
A_v1 a_1(a_3);
A a(a_3);
bool r = perform_test_ser_vers<A_v1>(a);
ASSERT_TRUE(r);
r = perform_test_ser_vers<A_v2>(a);
ASSERT_TRUE(r);
r = perform_test_ser_vers<A_v3>(a);
ASSERT_TRUE(r);
r = perform_test_ser_vers<A_v2>(a_1);
ASSERT_TRUE(r);
r = perform_test_ser_vers<A_v3>(a_1);
ASSERT_TRUE(r);
r = perform_test_ser_vers<A_v3>(a_2);
ASSERT_TRUE(r);
r = perform_test_ser_vers<A_v3>(a_3);
ASSERT_TRUE(r);
}