parent
3551ab3c80
commit
c0918a8fa2
@ -0,0 +1,129 @@
|
||||
#include "UniversalIdentifier.hpp"
|
||||
|
||||
namespace xmreg
|
||||
{
|
||||
|
||||
void
|
||||
Output::identify(transaction const& tx,
|
||||
public_key const& tx_pub_key)
|
||||
{
|
||||
cout << "Outputs identificataion" << endl;
|
||||
|
||||
|
||||
bool tx_is_coinbase = is_coinbase(tx);
|
||||
|
||||
key_derivation derivation;
|
||||
|
||||
if (!generate_key_derivation(tx_pub_key,
|
||||
*get_viewkey(), derivation))
|
||||
{
|
||||
throw std::runtime_error("Cant get derived key for a tx");
|
||||
}
|
||||
|
||||
for (uint64_t i = 0; i < tx.vout.size(); ++i)
|
||||
{
|
||||
// i will act as output indxes in the tx
|
||||
|
||||
if (tx.vout[i].target.type() != typeid(txout_to_key))
|
||||
continue;
|
||||
|
||||
// get tx input key
|
||||
txout_to_key const& txout_key
|
||||
= boost::get<txout_to_key>(tx.vout[i].target);
|
||||
|
||||
uint64_t amount = tx.vout[i].amount;
|
||||
|
||||
// get the tx output public key
|
||||
// that normally would be generated for us,
|
||||
// if someone had sent us some xmr.
|
||||
public_key generated_tx_pubkey;
|
||||
|
||||
derive_public_key(derivation,
|
||||
i,
|
||||
get_address()->address.m_spend_public_key,
|
||||
generated_tx_pubkey);
|
||||
|
||||
// check if generated public key matches the current output's key
|
||||
bool mine_output = (txout_key.key == generated_tx_pubkey);
|
||||
|
||||
|
||||
// placeholder variable for ringct outputs info
|
||||
// that we need to save in database
|
||||
|
||||
rct::key rtc_outpk {0};
|
||||
rct::key rtc_mask {0};
|
||||
rct::key rtc_amount {0};
|
||||
|
||||
// if mine output has RingCT, i.e., tx version is 2
|
||||
// need to decode its amount. otherwise its zero.
|
||||
if (mine_output && tx.version == 2)
|
||||
{
|
||||
// initialize with regular amount value
|
||||
// for ringct, except coinbase, it will be 0
|
||||
uint64_t rct_amount_val = amount;
|
||||
|
||||
// cointbase txs have amounts in plain sight.
|
||||
// so use amount from ringct, only for non-coinbase txs
|
||||
if (!tx_is_coinbase)
|
||||
{
|
||||
bool r;
|
||||
|
||||
// for ringct non-coinbase txs, these values are given
|
||||
// with txs.
|
||||
// coinbase ringctx dont have this information. we will provide
|
||||
// them only when needed, in get_unspent_outputs. So go there
|
||||
// to see how we deal with ringct coinbase txs when we spent
|
||||
// them
|
||||
// go to CurrentBlockchainStatus::construct_output_rct_field
|
||||
// to see how we deal with coinbase ringct that are used
|
||||
// as mixins
|
||||
|
||||
rtc_outpk = tx.rct_signatures.outPk[i].mask;
|
||||
rtc_mask = tx.rct_signatures.ecdhInfo[i].mask;
|
||||
rtc_amount = tx.rct_signatures.ecdhInfo[i].amount;
|
||||
|
||||
rct::key mask = tx.rct_signatures
|
||||
.ecdhInfo[i].mask;
|
||||
|
||||
r = decode_ringct(tx.rct_signatures,
|
||||
tx_pub_key,
|
||||
*get_viewkey(),
|
||||
i,
|
||||
mask,
|
||||
rct_amount_val);
|
||||
|
||||
if (!r)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Cant decode ringCT!");
|
||||
}
|
||||
|
||||
amount = rct_amount_val;
|
||||
|
||||
} // if (!tx_is_coinbase)
|
||||
|
||||
} // if (mine_output && tx.version == 2)
|
||||
|
||||
if (mine_output)
|
||||
{
|
||||
total_received += amount;
|
||||
|
||||
identified_outputs.emplace_back(
|
||||
info{
|
||||
txout_key.key, amount, i,
|
||||
rtc_outpk, rtc_mask, rtc_amount
|
||||
});
|
||||
|
||||
} // if (mine_output)
|
||||
|
||||
} // for (uint64_t i = 0; i < tx.vout.size(); ++i)
|
||||
}
|
||||
|
||||
void Input::identify(transaction const& tx,
|
||||
public_key const& tx_pub_key)
|
||||
{
|
||||
cout << "Inputs identificataion" << endl;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,235 @@
|
||||
#pragma once
|
||||
|
||||
#include "om_log.h"
|
||||
#include "tools.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) = 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) = 0;
|
||||
|
||||
inline auto get_address() const {return address_info;}
|
||||
inline auto get_viewkey() const {return viewkey;}
|
||||
|
||||
virtual ~BaseIdentifier() = default;
|
||||
|
||||
private:
|
||||
|
||||
address_parse_info const* address_info {nullptr};
|
||||
secret_key const* viewkey {nullptr};
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Output : public BaseIdentifier
|
||||
{
|
||||
struct info
|
||||
{
|
||||
public_key pub_key;
|
||||
uint64_t amount;
|
||||
uint64_t idx_in_tx;
|
||||
rct::key rtc_outpk;
|
||||
rct::key rtc_mask;
|
||||
rct::key rtc_amount;
|
||||
};
|
||||
|
||||
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) override;
|
||||
|
||||
inline auto get_outputs() const
|
||||
{
|
||||
return identified_outputs;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint64_t total_received {0};
|
||||
vector<info> identified_outputs;
|
||||
};
|
||||
|
||||
class Input : public BaseIdentifier
|
||||
{
|
||||
struct info
|
||||
{
|
||||
key_image key_img;
|
||||
uint64_t amount;
|
||||
public_key out_pub_key;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
using key_imgs_map_t = unordered_map<public_key, uint64_t>;
|
||||
|
||||
Input(address_parse_info const* _a,
|
||||
secret_key const* _viewkey,
|
||||
secret_key const* _spendkey,
|
||||
key_imgs_map_t const* _known_outputs)
|
||||
: BaseIdentifier(_a, _viewkey),
|
||||
spendkey {_spendkey},
|
||||
known_outputs {_known_outputs}
|
||||
{}
|
||||
|
||||
Input(address_parse_info const* _a,
|
||||
secret_key const* _viewkey,
|
||||
secret_key const* _spendkey)
|
||||
: Input(_a, _viewkey, _spendkey, nullptr)
|
||||
{}
|
||||
|
||||
Input(address_parse_info const* _a,
|
||||
secret_key const* _viewkey,
|
||||
key_imgs_map_t* _known_outputs)
|
||||
: Input(_a, _viewkey, nullptr, _known_outputs)
|
||||
{}
|
||||
|
||||
|
||||
void identify(transaction const& tx,
|
||||
public_key const& tx_pub_key) override;
|
||||
|
||||
private:
|
||||
secret_key const* viewkey;
|
||||
secret_key const* spendkey;
|
||||
key_imgs_map_t const* known_outputs {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) 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 (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_id() const {return payment_id;}
|
||||
|
||||
private:
|
||||
HashT payment_id {};
|
||||
HashT null_hash {0};
|
||||
|
||||
};
|
||||
|
||||
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}
|
||||
{
|
||||
tx_pub_key = get_tx_pub_key_from_received_outs(tx);
|
||||
}
|
||||
|
||||
void identify()
|
||||
{
|
||||
auto b = {(std::get<unique_ptr<T>>(
|
||||
identifiers)->identify(tx, tx_pub_key),
|
||||
true)...};
|
||||
(void) b;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
U* const get()
|
||||
{
|
||||
return std::get<unique_ptr<U>>(identifiers).get();
|
||||
}
|
||||
|
||||
inline auto get_tx_pub_key() const {return tx_pub_key;}
|
||||
|
||||
private:
|
||||
transaction const& tx;
|
||||
public_key tx_pub_key;
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<typename... T>
|
||||
auto make_identifier(transaction const& tx, T&&... identifiers)
|
||||
{
|
||||
return ModularIdentifier<typename T::element_type...>(
|
||||
tx, std::forward<T>(identifiers)...);
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue