ModularIdentifier development started

new_rpc
moneroexamples 6 years ago
parent 3551ab3c80
commit c0918a8fa2

@ -19,6 +19,7 @@ set(SOURCE_FILES
ThreadRAII.cpp
MysqlPing.cpp
TxUnlockChecker.cpp
UniversalIdentifier.cpp
RandomOutputs.cpp)
# make static library called libmyxrm

@ -500,8 +500,7 @@ CurrentBlockchainStatus::search_if_payment_made(
PaymentSearcher<crypto::hash8> tx_searcher {
bc_setup.import_payment_address,
bc_setup.import_payment_viewkey,
mcore.get()};
bc_setup.import_payment_viewkey};
auto found_amount_pair = std::make_pair(0ull, std::cend(txs_to_check));

@ -163,4 +163,87 @@ private:
const transaction* tx;
};
//class BaseIdentifier {
//public:
// BaseIdentifier(address_parse_info const* _a,
// const secret_key* _v,
// const transaction* _tx)
// : address_info {_a}, viewkey {_v}, tx {_tx}
// {
// }
// virtual void identify() = 0;
//protected:
// // address and viewkey for this search thread.
// address_parse_info const* address_info;
// secret_key const* viewkey;
// // transaction that is beeing search
// transaction const* tx;
//};
//class OutputIdentifier : public BaseIdentifier
//{
// using BaseIdentifier::BaseIdentifier;
// using key_imgs_map = unordered_map<public_key, uint64_t>;
// // define a structure to keep information about found
// // outputs that we can need in later parts.
// struct output_info
// {
// public_key pub_key;
// uint64_t amount;
// uint64_t idx_in_tx;
// string rtc_outpk;
// string rtc_mask;
// string rtc_amount;
// };
//public:
// void
// set_known_outputs(key_imgs_map const* _known_outputs)
// {
// known_outputs_keys = _known_outputs;
// }
// void
// identify()
// {}
//private:
// key_imgs_map const* known_outputs_keys {nullptr};
//};
//class InpputIdentifier : public BaseIdentifier
//{
// using BaseIdentifier::BaseIdentifier;
// // define a structure to keep information about found
// // inputs that we can need in later parts.
// struct input_info
// {
// string key_img;
// uint64_t amount;
// public_key out_pub_key;
// };
//public:
// void
// identify()
// {}
//};
}

@ -2,6 +2,7 @@
#include "om_log.h"
#include "OutputInputIdentification.h"
#include "UniversalIdentifier.hpp"
#include <map>
#include <utility>
@ -24,17 +25,13 @@ class PaymentSearcherException: public std::runtime_error
template<typename Hash_T>
class PaymentSearcher
{
// null hash value for hash8 or regular hash
using null_hash_T = boost::value_initialized<Hash_T>;
public:
PaymentSearcher(
address_parse_info const& _address_info,
secret_key const& _view_key,
MicroCore* const _mcore):
secret_key const& _viewkey):
address_info {_address_info},
view_key {_view_key},
mcore {_mcore}
viewkey {_viewkey}
{}
@ -55,8 +52,7 @@ public:
// iterator to last txs that we found containing
// our payment
typename Cont_T<transaction>::const_iterator found_tx_it
= std::cend(txs);
auto found_tx_it = std::cend(txs);
for (auto it = std::cbegin(txs);
it != std::cend(txs); ++it)
@ -68,17 +64,18 @@ public:
if (skip_coinbase && is_coinbase_tx)
continue;
// get payment id. by default we are intrested
// in short ids from integrated addresses
auto payment_id_tuple = xmreg::get_payment_id(tx);
auto identifier = make_identifier(tx,
make_unique<Output>(&address_info, &viewkey),
make_unique<IntegratedPaymentID>(&address_info, &viewkey));
auto pay_id = std::get<Hash_T>(payment_id_tuple);
if (pay_id == null_hash)
continue;
auto tx_pub_key = identifier.get_tx_pub_key();
identifier.template get<IntegratedPaymentID>()
->identify(tx, tx_pub_key);
public_key tx_pub_key
= xmreg::get_tx_pub_key_from_received_outs(tx);
auto pay_id = identifier.template get<IntegratedPaymentID>()
->get_id();
// we have pay_id. it can be crypto::hash8 or crypto:hash
// so naw we need to perform comparison of the pay_id found
@ -86,12 +83,6 @@ public:
// for hash8 we need to do decoding of the pay_id, as it is
// encoded
if (!payment_id_decryptor(pay_id, tx_pub_key))
{
throw PaymentSearcherException("Cant decrypt pay_id: "
+ pod_to_hex(pay_id));
}
if (pay_id != expected_payment_id)
continue;
@ -101,22 +92,18 @@ public:
// for each output, in a tx, check if it belongs
// to the given account of specific address and viewkey
auto tx_hash = get_transaction_hash(tx);
identifier.template get<Output>()->identify(tx, tx_pub_key);
OutputInputIdentification oi_identification {
&address_info, &view_key, &tx,
tx_hash, is_coinbase_tx};
auto const& outputs_found
= identifier.template get<Output>()->get_outputs();
oi_identification.identify_outputs();
if (!oi_identification.identified_outputs.empty())
if (!outputs_found.empty())
{ // nothing was found
make_pair(found_amount, found_tx_it);
}
// now add the found outputs into Outputs tables
for (auto& out_info: oi_identification.identified_outputs)
for (auto& out_info: outputs_found)
found_amount += out_info.amount;
if (found_amount > 0)
@ -126,35 +113,11 @@ public:
return make_pair(found_amount, found_tx_it);
}
virtual ~PaymentSearcher() = default;
private:
address_parse_info const& address_info;
secret_key const& view_key;
Hash_T payment_id;
MicroCore* const mcore;
inline bool
payment_id_decryptor(
crypto::hash& payment_id,
public_key const& tx_pub_key)
{
// don't need to do anything for legacy payment ids
return true;
}
inline bool
payment_id_decryptor(
crypto::hash8& payment_id,
public_key const& tx_pub_key)
{
// overload for short payment id,
// the we are going to decrypt
return mcore->decrypt_payment_id(
payment_id, tx_pub_key, view_key);
}
secret_key const& viewkey;
};

@ -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)...);
}
}

@ -710,6 +710,33 @@ get_payment_id(const vector<uint8_t>& extra,
}
// just a copy from bool
// device_default::encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key)
bool
encrypt_payment_id(crypto::hash8 &payment_id,
const crypto::public_key &public_key,
const crypto::secret_key &secret_key)
{
#define ENCRYPTED_PAYMENT_ID_TAIL 0x8d
crypto::key_derivation derivation;
crypto::hash hash;
char data[33]; /* A hash, and an extra byte */
if (!generate_key_derivation(public_key, secret_key, derivation))
return false;
memcpy(data, &derivation, 32);
data[32] = ENCRYPTED_PAYMENT_ID_TAIL;
cn_fast_hash(data, 33, hash);
for (size_t b = 0; b < 8; ++b)
payment_id.data[b] ^= hash.data[b];
return true;
}
array<size_t, 5>
timestamp_difference(uint64_t t1, uint64_t t2)
{

@ -178,6 +178,12 @@ get_payment_id(transaction const& tx)
return make_tuple(payment_id, payment_id8);
}
// Encryption and decryption are the same operation (xor with a key)
bool
encrypt_payment_id(crypto::hash8 &payment_id,
const crypto::public_key &public_key,
const crypto::secret_key &secret_key);
inline double
get_xmr(uint64_t core_amount)

@ -23,6 +23,7 @@ add_om_test(mysql)
add_om_test(microcore)
add_om_test(bcstatus)
add_om_test(txsearch)
add_om_test(universalidentifier)
SETUP_TARGET_FOR_COVERAGE(
NAME mysql_cov
@ -40,6 +41,10 @@ SETUP_TARGET_FOR_COVERAGE(
NAME txsearch_cov
EXECUTABLE txsearch_tests)
SETUP_TARGET_FOR_COVERAGE(
NAME universalidentifier_cov
EXECUTABLE universalidentifier_tests)
add_custom_target(cov
COMMAND ;
DEPENDS mysql_cov microcore_cov bcstatus_cov txsearch_cov

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save