You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
333 lines
8.3 KiB
333 lines
8.3 KiB
#pragma once
|
|
|
|
#include "om_log.h"
|
|
#include "tools.h"
|
|
#include "MicroCore.h"
|
|
|
|
#include <tuple>
|
|
#include <utility>
|
|
|
|
namespace xmreg
|
|
{
|
|
using namespace std;
|
|
|
|
|
|
class AbstractIdentifier
|
|
{
|
|
public:
|
|
virtual void identify(transaction const& tx,
|
|
public_key const& tx_pub_key,
|
|
vector<public_key> const& additional_tx_pub_keys
|
|
= vector<public_key>{}) = 0;
|
|
};
|
|
|
|
|
|
class BaseIdentifier : public AbstractIdentifier
|
|
{
|
|
public:
|
|
BaseIdentifier(
|
|
address_parse_info const* _address,
|
|
secret_key const* _viewkey)
|
|
: address_info {_address}, viewkey {_viewkey}
|
|
{}
|
|
|
|
virtual void identify(transaction const& tx,
|
|
public_key const& tx_pub_key,
|
|
vector<public_key> const& additional_tx_pub_keys
|
|
= vector<public_key>{}) = 0;
|
|
|
|
inline auto get_address() const {return address_info;}
|
|
inline auto get_viewkey() const {return viewkey;}
|
|
inline auto get_total() const {return total_xmr;}
|
|
|
|
virtual ~BaseIdentifier() = default;
|
|
|
|
protected:
|
|
address_parse_info const* address_info {nullptr};
|
|
secret_key const* viewkey {nullptr};
|
|
uint64_t total_xmr {0};
|
|
};
|
|
|
|
/**
|
|
* @brief The Output class identifies our
|
|
* outputs in a given tx
|
|
*/
|
|
class Output : public BaseIdentifier
|
|
{
|
|
public:
|
|
|
|
Output(address_parse_info const* _address,
|
|
secret_key const* _viewkey)
|
|
: BaseIdentifier(_address, _viewkey)
|
|
{}
|
|
|
|
void identify(transaction const& tx,
|
|
public_key const& tx_pub_key,
|
|
vector<public_key> const& additional_tx_pub_keys
|
|
= vector<public_key>{}) override;
|
|
|
|
inline auto get() const
|
|
{
|
|
return identified_outputs;
|
|
}
|
|
|
|
struct info
|
|
{
|
|
public_key pub_key;
|
|
uint64_t amount;
|
|
uint64_t idx_in_tx;
|
|
key_derivation derivation;
|
|
rct::key rtc_outpk;
|
|
rct::key rtc_mask;
|
|
rct::key rtc_amount;
|
|
|
|
friend std::ostream& operator<<(std::ostream& os, info const& _info);
|
|
};
|
|
|
|
protected:
|
|
|
|
uint64_t total_received {0};
|
|
vector<info> identified_outputs;
|
|
};
|
|
|
|
/**
|
|
* @brief The Input class identifies our possible
|
|
* inputs (key images) in a given tx
|
|
*/
|
|
class Input : public BaseIdentifier
|
|
{
|
|
public:
|
|
//output_pubk , amount
|
|
using known_outputs_t = unordered_map<public_key, uint64_t>;
|
|
|
|
Input(address_parse_info const* _a,
|
|
secret_key const* _viewkey,
|
|
known_outputs_t const* _known_outputs,
|
|
MicroCore* _mcore)
|
|
: BaseIdentifier(_a, _viewkey),
|
|
known_outputs {_known_outputs},
|
|
mcore {_mcore}
|
|
{}
|
|
|
|
void identify(transaction const& tx,
|
|
public_key const& tx_pub_key,
|
|
vector<public_key> const& additional_tx_pub_keys
|
|
= vector<public_key>{}) override;
|
|
|
|
inline auto get() const
|
|
{
|
|
return identified_inputs;
|
|
}
|
|
|
|
|
|
struct info
|
|
{
|
|
key_image key_img;
|
|
uint64_t amount;
|
|
public_key out_pub_key;
|
|
|
|
friend std::ostream& operator<<(std::ostream& os, info const& _info);
|
|
};
|
|
|
|
|
|
protected:
|
|
|
|
secret_key const* viewkey {nullptr};
|
|
known_outputs_t const* known_outputs {nullptr};
|
|
MicroCore* mcore {nullptr};
|
|
vector<info> identified_inputs;
|
|
};
|
|
|
|
/**
|
|
* Spendkey is optional. But if we have it,
|
|
* we can for sure determine which key images
|
|
* are ours or not. This is especially useful
|
|
* in unit testing, since we can compare wether
|
|
* guessed key images do contain all our key images
|
|
*/
|
|
class RealInput : public Input
|
|
{
|
|
|
|
public:
|
|
|
|
RealInput(address_parse_info const* _a,
|
|
secret_key const* _viewkey,
|
|
secret_key const* _spendkey,
|
|
MicroCore* _mcore)
|
|
: Input(_a, _viewkey, nullptr, _mcore),
|
|
spendkey {_spendkey}
|
|
{}
|
|
|
|
void identify(transaction const& tx,
|
|
public_key const& tx_pub_key,
|
|
vector<public_key> const& additional_tx_pub_keys
|
|
= vector<public_key>{}) override;
|
|
|
|
|
|
protected:
|
|
secret_key const* spendkey {nullptr};
|
|
};
|
|
|
|
|
|
template <typename HashT>
|
|
class PaymentID : public BaseIdentifier
|
|
{
|
|
|
|
public:
|
|
|
|
PaymentID(address_parse_info const* _address,
|
|
secret_key const* _viewkey)
|
|
: BaseIdentifier(_address, _viewkey)
|
|
{}
|
|
|
|
void identify(transaction const& tx,
|
|
public_key const& tx_pub_key,
|
|
vector<public_key> const& additional_tx_pub_keys
|
|
= vector<public_key>{}) override
|
|
{
|
|
cout << "PaymentID decryption: "
|
|
+ pod_to_hex(payment_id) << endl;
|
|
|
|
// get payment id. by default we are intrested
|
|
// in short ids from integrated addresses
|
|
auto payment_id_tuple = xmreg::get_payment_id(tx);
|
|
|
|
payment_id = std::get<HashT>(payment_id_tuple);
|
|
|
|
// if no payment_id found, return
|
|
if (payment_id == null_hash)
|
|
return;
|
|
|
|
// decrypt integrated payment id. if its legacy payment id
|
|
// nothing will happen.
|
|
if (!decrypt(payment_id, tx_pub_key))
|
|
{
|
|
throw std::runtime_error("Cant decrypt pay_id: "
|
|
+ pod_to_hex(payment_id));
|
|
}
|
|
}
|
|
|
|
inline bool
|
|
decrypt(crypto::hash& p_id,
|
|
public_key const& tx_pub_key) const
|
|
{
|
|
// don't need to do anything for legacy payment ids
|
|
return true;
|
|
}
|
|
|
|
inline bool
|
|
decrypt(crypto::hash8& p_id,
|
|
public_key const& tx_pub_key) const
|
|
{
|
|
// overload for short payment id,
|
|
// the we are going to decrypt
|
|
return xmreg::encrypt_payment_id(
|
|
p_id, tx_pub_key, *get_viewkey());
|
|
}
|
|
|
|
inline auto get() const {return payment_id;}
|
|
|
|
private:
|
|
HashT payment_id {};
|
|
HashT null_hash {};
|
|
};
|
|
|
|
using LegacyPaymentID = PaymentID<crypto::hash>;
|
|
using IntegratedPaymentID = PaymentID<crypto::hash8>;
|
|
|
|
|
|
template<typename... T>
|
|
class ModularIdentifier
|
|
{
|
|
public:
|
|
tuple<unique_ptr<T>...> identifiers;
|
|
|
|
ModularIdentifier(transaction const& _tx,
|
|
unique_ptr<T>... args)
|
|
: identifiers {move(args)...},
|
|
tx {_tx}
|
|
{
|
|
// having tx public key is very common for all identifiers
|
|
// so we can get it here, instead of just obtaining it
|
|
// for each identifier seprately
|
|
tx_pub_key = get_tx_pub_key_from_received_outs(tx);
|
|
|
|
// multi-output txs can have some additional public keys
|
|
// in the extra field. So we also get them, just in case
|
|
additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(tx);
|
|
}
|
|
|
|
void identify()
|
|
{
|
|
auto b = {(std::get<unique_ptr<T>>(
|
|
identifiers)->identify(
|
|
tx, tx_pub_key, additional_tx_pub_keys),
|
|
true)...};
|
|
(void) b;
|
|
}
|
|
|
|
// overload to get value from tuple by type
|
|
template <typename U>
|
|
auto* const get()
|
|
{
|
|
return std::get<unique_ptr<U>>(identifiers).get();
|
|
}
|
|
|
|
|
|
// overload to get value from tuple by number
|
|
template <size_t No>
|
|
auto* const get()
|
|
{
|
|
return std::get<No>(identifiers).get();
|
|
}
|
|
|
|
inline auto get_tx_pub_key() const {return tx_pub_key;}
|
|
|
|
private:
|
|
transaction const& tx;
|
|
public_key tx_pub_key;
|
|
vector<public_key> additional_tx_pub_keys;
|
|
};
|
|
|
|
/**
|
|
* A helper function to create ModularIdentifier object
|
|
*/
|
|
template<typename... T>
|
|
auto make_identifier(transaction const& tx, T&&... identifiers)
|
|
{
|
|
return ModularIdentifier<typename T::element_type...>(
|
|
tx, std::forward<T>(identifiers)...);
|
|
}
|
|
|
|
template <typename T>
|
|
auto
|
|
calc_total_xmr(T&& infos)
|
|
{
|
|
uint64_t total_xmr {0};
|
|
|
|
for (auto const& info: infos)
|
|
total_xmr += info.amount;
|
|
|
|
return total_xmr;
|
|
}
|
|
|
|
|
|
inline std::ostream&
|
|
operator<<(std::ostream& os, xmreg::Output::info const& _info)
|
|
{
|
|
return os << _info.idx_in_tx << ", "
|
|
<< pod_to_hex(_info.pub_key) << ", "
|
|
<< _info.amount;
|
|
}
|
|
|
|
inline std::ostream&
|
|
operator<<(std::ostream& os, xmreg::Input::info const& _info)
|
|
{
|
|
return os << pod_to_hex(_info.key_img) << ", "
|
|
<< pod_to_hex(_info.out_pub_key) << ", "
|
|
<< _info.amount;
|
|
}
|
|
|
|
}
|
|
|