blockchain/src/currency_core/offers_services_helpers.h
2021-11-04 11:42:11 +01:00

234 lines
8.7 KiB
C++

// Copyright (c) 2014-2018 Zano Project
// Copyright (c) 2014-2018 The Louisdor Project
// Copyright (c) 2012-2013 The Boolberry developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include "profile_tools.h"
#include "serialization/keyvalue_serialization.h"
#include "storages/portable_storage_template_helper.h"
#include "currency_basic.h"
#include "offers_service_basics.h"
#include "currency_protocol/blobdatatype.h"
#include "zlib_helper.h"
#include "bc_offers_service_basic.h"
#include "bc_attachments_helpers.h"
namespace bc_services
{
struct offer_id
{
crypto::hash tx_id;
uint64_t index;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_POD_AS_HEX_STRING(tx_id)
KV_SERIALIZE(index)
END_KV_SERIALIZE_MAP()
};
#define ORDER_BY_TIMESTAMP 0
#define ORDER_BY_AMOUNT_PRIMARY 1
#define ORDER_BY_AMOUNT_TARGET 2
#define ORDER_BY_AMOUNT_RATE 3
#define ORDER_BY_PAYMENT_TYPES 4
#define ORDER_BY_CONTACTS 5
#define ORDER_BY_LOCATION 6
#define ORDER_BY_NAME 7
#define ORDER_CALLBACKS_COUNT 8
typedef std::wstring(*to_low_case_ptr_type)(const std::wstring& soruce);
void set_external_to_low_converter(to_low_case_ptr_type cb);
typedef bool(*sort_offers_func_type)(const offer_details_ex* a, const offer_details_ex* b);
extern std::vector<sort_offers_func_type> gsort_offers_predicates;
bool is_offer_matched_by_filter(const offer_details_ex& o, const core_offers_filter& of, uint64_t currnet_time);
bool filter_offers_list(std::list<offer_details_ex>& offers, const core_offers_filter& filter, uint64_t current_core_time);
crypto::hash offer_id_from_hash_and_index(const crypto::hash& tx_id, uint64_t index);
crypto::hash offer_id_from_hash_and_index(const offer_id& oid);
const crypto::public_key get_offer_secure_key_by_index_from_tx(const currency::transaction& tx, size_t index);
inline double calculate_offer_rate(const offer_details& od)
{
return od.amount_primary > 0 ? static_cast<double>(od.amount_target) / od.amount_primary : 0;
}
template<class offer_instruction_t>
void put_offer_into_attachment(const offer_instruction_t& oi, std::vector<currency::attachment_v>& att_container)
{
std::string json_buff;
currency::tx_service_attachment att = AUTO_VAL_INIT(att);
bool r = bc_services::pack_attachment_as_gzipped_json(oi, att);
CHECK_AND_ASSERT_MES(r, void(), "Failed to pack_attachment_as_gzipped_json");
att.service_id = BC_OFFERS_SERVICE_ID;
if (typeid(offer_instruction_t) == typeid(offer_details))
{
att.instruction = BC_OFFERS_SERVICE_INSTRUCTION_ADD;
}
else if (typeid(offer_instruction_t) == typeid(update_offer))
{
att.instruction = BC_OFFERS_SERVICE_INSTRUCTION_UPD;
}
else if (typeid(offer_instruction_t) == typeid(cancel_offer))
{
att.instruction = BC_OFFERS_SERVICE_INSTRUCTION_DEL;
}
else
{
LOG_ERROR("Filed to pack tx_service_attachment in bc_offers_service, unknown_type: " << typeid(offer_instruction_t).name());
return;
}
//if att.security vector contain public_key then transaction constructor put there correct public_key related with one time transaction keys
if (att.instruction == BC_OFFERS_SERVICE_INSTRUCTION_ADD || att.instruction == BC_OFFERS_SERVICE_INSTRUCTION_UPD)
att.security.push_back(currency::null_pkey);
att_container.push_back(att);
}
inline currency::blobdata make_offer_sig_blob(const update_offer& uo)
{
currency::blobdata bd;
epee::string_tools::append_pod_to_strbuff(bd, uo.tx_id);
epee::string_tools::append_pod_to_strbuff(bd, uo.offer_index);
bd += epee::serialization::store_t_to_binary(uo.of);
return bd;
}
inline currency::blobdata make_offer_sig_blob(const cancel_offer& co)
{
currency::blobdata bd;
epee::string_tools::append_pod_to_strbuff(bd, co.tx_id);
epee::string_tools::append_pod_to_strbuff(bd, co.offer_index);
return bd;
}
//----------------------------------------------------------------------------------------------------
template<class t_contained_type, class t_srv_attachments_container>
bool extract_type_and_add(const std::string& body, t_srv_attachments_container& srv_cnt)
{
std::string json_buff;
if (!epee::zlib_helper::unpack(body, json_buff))
{
LOG_ERROR("Filed to unpack tx_service_attachment in bc_offers_service, tx_id");
return false;
}
t_contained_type obj = AUTO_VAL_INIT(obj);
bool r = epee::serialization::load_t_from_json(obj, json_buff);
if (!r)
{
LOG_ERROR("Filed to load json from tx_service_attachment in bc_offers_service, body: " << body);
return false;
}
srv_cnt.push_back(obj);
return true;
}
//----------------------------------------------------------------------------------------------------
template<class t_srv_attachments_container, class t_tx_attachments_container>
void extract_market_instructions(t_srv_attachments_container& cnt, const t_tx_attachments_container& raw_att)
{
PROFILE_FUNC("bc_service::extract_market_instructions");
for (auto& att : raw_att)
{
if (att.type() == typeid(currency::tx_service_attachment))
{
const currency::tx_service_attachment& sa = boost::get<const currency::tx_service_attachment>(att);
if (sa.service_id == BC_OFFERS_SERVICE_ID)
{
if (sa.instruction == BC_OFFERS_SERVICE_INSTRUCTION_ADD)
{
extract_type_and_add<bc_services::offer_details>(sa.body, cnt);
}
else if (sa.instruction == BC_OFFERS_SERVICE_INSTRUCTION_UPD)
{
extract_type_and_add<bc_services::update_offer>(sa.body, cnt);
}
else if (sa.instruction == BC_OFFERS_SERVICE_INSTRUCTION_DEL)
{
extract_type_and_add<bc_services::cancel_offer>(sa.body, cnt);
}
}
}
}
}
#define OFFER_TYPE_PRIMARY_TO_TARGET 0
#define OFFER_TYPE_TARGET_TO_PRIMARY 1
#define OFFER_TYPE_GOODS_TO_PRIMARY 2
#define OFFER_TYPE_PRIMARY_TO_GOODS 3
#define OFFER_TYPE_MASK_PRIMARY_TO_TARGET 0x00000001
#define OFFER_TYPE_MASK_TARGET_TO_PRIMARY 0x00000002
#define OFFER_TYPE_MASK_GOODS_TO_PRIMARY 0x00000004
#define OFFER_TYPE_MASK_PRIMARY_TO_GOODS 0x00000008
#define OFFER_TYPE_UNDEFINED 255
struct offer_details_ex_with_hash : public offer_details_ex
{
crypto::hash h;
mutable std::string nxt_offer; //in case of updated offer
};
typedef offer_details_ex_with_hash odeh;
inline crypto::hash extract_id(const odeh& v) { return v.h; }
inline uint64_t extrct_timestamp(const odeh& v) { return v.timestamp; }
inline uint64_t extract_amount_primary(const odeh& v) { return v.amount_primary; }
inline uint64_t extract_amount_target(const odeh& v) { return v.amount_target; }
inline double extract_rate(const odeh& v) { return calculate_offer_rate(v); }
inline size_t extract_payment_types(const odeh& v) { return v.payment_types.size(); }
inline std::string extract_contacts(const odeh& v) { return v.contacts; }
inline std::string extract_location(const odeh& v) {
#ifndef MOBILE_WALLET_BUILD
return currency::utf8_to_lower(v.location_country + v.location_city);
#else
return "UNSUPORTED";
#endif
}
inline std::string extract_name(const odeh& v) {
#ifndef MOBILE_WALLET_BUILD
return currency::utf8_to_lower(v.target);
#else
return "UNSUPORTED";
#endif
}
template<int sort_type>
struct sort_id_to_type
{};
#define TAG_NAME(tag_name) struct tag_name{};
TAG_NAME(by_id);
TAG_NAME(by_timestamp);
TAG_NAME(by_amount_primary);
TAG_NAME(by_amount_target);
TAG_NAME(by_rate);
TAG_NAME(by_payment_types);
TAG_NAME(by_contacts);
TAG_NAME(by_location);
TAG_NAME(by_name);
#undef TAG_NAME
template<> struct sort_id_to_type<ORDER_BY_TIMESTAMP> { typedef by_timestamp index_type; };
template<> struct sort_id_to_type<ORDER_BY_AMOUNT_PRIMARY> { typedef by_amount_primary index_type; };
template<> struct sort_id_to_type<ORDER_BY_AMOUNT_TARGET> { typedef by_amount_target index_type; };
template<> struct sort_id_to_type<ORDER_BY_AMOUNT_RATE> { typedef by_rate index_type; };
template<> struct sort_id_to_type<ORDER_BY_PAYMENT_TYPES> { typedef by_payment_types index_type; };
template<> struct sort_id_to_type<ORDER_BY_CONTACTS> { typedef by_contacts index_type; };
template<> struct sort_id_to_type<ORDER_BY_LOCATION> { typedef by_location index_type; };
template<> struct sort_id_to_type<ORDER_BY_NAME> { typedef by_name index_type; };
}