parent
90cb73f711
commit
001eb33daf
@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// Created by mwo on 24/05/15.
|
||||||
|
//
|
||||||
|
// source: http://codereview.stackexchange.com/questions/13176/infix-iterator-code
|
||||||
|
|
||||||
|
// infix_iterator.h
|
||||||
|
#if !defined(INFIX_ITERATOR_H_)
|
||||||
|
#define INFIX_ITERATOR_H_
|
||||||
|
#include <ostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
template <class T, class charT=char, class traits=std::char_traits<charT> >
|
||||||
|
class infix_ostream_iterator :
|
||||||
|
public std::iterator<std::output_iterator_tag, void, void, void, void>
|
||||||
|
{
|
||||||
|
std::basic_ostream<charT,traits> *os;
|
||||||
|
std::basic_string<charT> delimiter;
|
||||||
|
std::basic_string<charT> real_delim;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef charT char_type;
|
||||||
|
typedef traits traits_type;
|
||||||
|
typedef std::basic_ostream<charT, traits> ostream_type;
|
||||||
|
|
||||||
|
infix_ostream_iterator(ostream_type &s)
|
||||||
|
: os(&s)
|
||||||
|
{}
|
||||||
|
|
||||||
|
infix_ostream_iterator(ostream_type &s, charT const *d)
|
||||||
|
: os(&s),
|
||||||
|
real_delim(d)
|
||||||
|
{}
|
||||||
|
|
||||||
|
infix_ostream_iterator<T, charT, traits> &operator=(T const &item)
|
||||||
|
{
|
||||||
|
*os << delimiter << item;
|
||||||
|
delimiter = real_delim;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
infix_ostream_iterator<T, charT, traits> &operator*() {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
infix_ostream_iterator<T, charT, traits> &operator++() {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
infix_ostream_iterator<T, charT, traits> &operator++(int) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,15 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.6)
|
||||||
|
|
||||||
|
project(myxrm)
|
||||||
|
|
||||||
|
set(SOURCE_FILES
|
||||||
|
MicroCore.cpp
|
||||||
|
tools.cpp
|
||||||
|
CmdLineOptions.cpp)
|
||||||
|
|
||||||
|
# make static library called libmyxrm
|
||||||
|
# that we are going to link to
|
||||||
|
# in the root CMakeLists.txt file
|
||||||
|
add_library(myxrm
|
||||||
|
STATIC
|
||||||
|
${SOURCE_FILES})
|
@ -0,0 +1,82 @@
|
|||||||
|
//
|
||||||
|
// Created by mwo on 6/11/15.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "CmdLineOptions.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmreg
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Take the acc and *avv[] from the main() and check and parse
|
||||||
|
* all the options given
|
||||||
|
*/
|
||||||
|
CmdLineOptions::CmdLineOptions(int acc, const char *avv[]) {
|
||||||
|
|
||||||
|
positional_options_description p;
|
||||||
|
|
||||||
|
p.add("txhash", -1);
|
||||||
|
|
||||||
|
options_description desc(
|
||||||
|
"xmrblocks, start Onion Monero Blockchain Explorer");
|
||||||
|
|
||||||
|
desc.add_options()
|
||||||
|
("help,h", value<bool>()->default_value(false)->implicit_value(true),
|
||||||
|
"produce help message")
|
||||||
|
("testnet,t", value<bool>()->default_value(false)->implicit_value(true),
|
||||||
|
"use testnet blockchain")
|
||||||
|
("enable-pusher", value<bool>()->default_value(false)->implicit_value(true),
|
||||||
|
"enable pushing signed tx")
|
||||||
|
("port,p", value<string>()->default_value("8081"),
|
||||||
|
"default port")
|
||||||
|
("bc-path,b", value<string>(),
|
||||||
|
"path to lmdb blockchain")
|
||||||
|
("custom-db-path,c", value<string>(),
|
||||||
|
"path to the custom lmdb database used for searching things")
|
||||||
|
("deamon-url,d", value<string>()->default_value("http:://127.0.0.1:18081"),
|
||||||
|
"monero address string");
|
||||||
|
|
||||||
|
|
||||||
|
store(command_line_parser(acc, avv)
|
||||||
|
.options(desc)
|
||||||
|
.positional(p)
|
||||||
|
.run(), vm);
|
||||||
|
|
||||||
|
notify(vm);
|
||||||
|
|
||||||
|
if (vm.count("help"))
|
||||||
|
{
|
||||||
|
if (vm["help"].as<bool>())
|
||||||
|
cout << desc << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the value of the argument passed to the program
|
||||||
|
* in wrapped around boost::optional
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
boost::optional<T>
|
||||||
|
CmdLineOptions::get_option(const string & opt_name) const
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!vm.count(opt_name))
|
||||||
|
{
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vm[opt_name].as<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// explicit instantiations of get_option template function
|
||||||
|
template boost::optional<string>
|
||||||
|
CmdLineOptions::get_option<string>(const string & opt_name) const;
|
||||||
|
|
||||||
|
template boost::optional<bool>
|
||||||
|
CmdLineOptions::get_option<bool>(const string & opt_name) const;
|
||||||
|
|
||||||
|
template boost::optional<size_t>
|
||||||
|
CmdLineOptions::get_option<size_t>(const string & opt_name) const;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// Created by mwo on 6/11/15.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef XMREG01_CMDLINEOPTIONS_H
|
||||||
|
#define XMREG01_CMDLINEOPTIONS_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
|
namespace xmreg
|
||||||
|
{
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace boost::program_options;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages program options of this example program.
|
||||||
|
*
|
||||||
|
* Basically a wrapper for boost::program_options
|
||||||
|
*/
|
||||||
|
class CmdLineOptions {
|
||||||
|
variables_map vm;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CmdLineOptions(int acc, const char *avv[]);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
boost::optional<T> get_option(const string & opt_name) const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //XMREG01_CMDLINEOPTIONS_H
|
@ -0,0 +1,353 @@
|
|||||||
|
//
|
||||||
|
// Created by mwo on 5/11/15.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "MicroCore.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// NOTE: These values should match blockchain.cpp
|
||||||
|
// TODO: Refactor
|
||||||
|
const uint64_t mainnet_hard_fork_version_1_till = 1009826;
|
||||||
|
const uint64_t testnet_hard_fork_version_1_till = 624633;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmreg
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The constructor is interesting, as
|
||||||
|
* m_mempool and m_blockchain_storage depend
|
||||||
|
* on each other.
|
||||||
|
*
|
||||||
|
* So basically m_mempool is initialized with
|
||||||
|
* reference to Blockchain (i.e., Blockchain&)
|
||||||
|
* and m_blockchain_storage is initialized with
|
||||||
|
* reference to m_mempool (i.e., tx_memory_pool&)
|
||||||
|
*
|
||||||
|
* The same is done in cryptonode::core.
|
||||||
|
*/
|
||||||
|
MicroCore::MicroCore():
|
||||||
|
m_mempool(m_blockchain_storage),
|
||||||
|
m_blockchain_storage(m_mempool)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialized the MicroCore object.
|
||||||
|
*
|
||||||
|
* Create BlockchainLMDB on the heap.
|
||||||
|
* Open database files located in blockchain_path.
|
||||||
|
* Initialize m_blockchain_storage with the BlockchainLMDB object.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
MicroCore::init(const string& _blockchain_path)
|
||||||
|
{
|
||||||
|
int db_flags = 0;
|
||||||
|
|
||||||
|
blockchain_path = _blockchain_path;
|
||||||
|
|
||||||
|
//db_flags |= MDB_RDONLY;
|
||||||
|
db_flags |= MDB_NOLOCK;
|
||||||
|
//db_flags |= MDB_SYNC;
|
||||||
|
|
||||||
|
// uint64_t DEFAULT_FLAGS = MDB_NOMETASYNC | MDB_NORDAHEAD;
|
||||||
|
|
||||||
|
//db_flags = DEFAULT_FLAGS;
|
||||||
|
|
||||||
|
HardFork* m_hardfork = nullptr;
|
||||||
|
|
||||||
|
BlockchainDB* db = nullptr;
|
||||||
|
db = new BlockchainLMDB();
|
||||||
|
|
||||||
|
bool use_testnet {false};
|
||||||
|
|
||||||
|
uint64_t hard_fork_version_1_till = use_testnet ? testnet_hard_fork_version_1_till : mainnet_hard_fork_version_1_till;
|
||||||
|
|
||||||
|
m_hardfork = new HardFork(*db, 1, hard_fork_version_1_till);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// try opening lmdb database files
|
||||||
|
db->open(blockchain_path, db_flags);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
cerr << "Error opening database: " << e.what();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the blockchain database
|
||||||
|
// is successful opened
|
||||||
|
if(!db->is_open())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize Blockchain object to manage
|
||||||
|
// the database.
|
||||||
|
return m_blockchain_storage.init(db, m_hardfork, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get m_blockchain_storage.
|
||||||
|
* Initialize m_blockchain_storage with the BlockchainLMDB object.
|
||||||
|
*/
|
||||||
|
Blockchain&
|
||||||
|
MicroCore::get_core()
|
||||||
|
{
|
||||||
|
return m_blockchain_storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get block by its height
|
||||||
|
*
|
||||||
|
* returns true if success
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
MicroCore::get_block_by_height(const uint64_t& height, block& blk)
|
||||||
|
{
|
||||||
|
|
||||||
|
crypto::hash block_id;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
block_id = m_blockchain_storage.get_block_id_by_height(height);
|
||||||
|
}
|
||||||
|
catch (const exception& e)
|
||||||
|
{
|
||||||
|
cerr << e.what() << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!m_blockchain_storage.get_block_by_hash(block_id, blk))
|
||||||
|
{
|
||||||
|
cerr << "Block with hash " << block_id
|
||||||
|
<< "and height " << height << " not found!"
|
||||||
|
<< endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get transaction tx from the blockchain using it hash
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
MicroCore::get_tx(const crypto::hash& tx_hash, transaction& tx)
|
||||||
|
{
|
||||||
|
if (m_blockchain_storage.have_tx(tx_hash))
|
||||||
|
{
|
||||||
|
// get transaction with given hash
|
||||||
|
tx = m_blockchain_storage.get_db().get_tx(tx_hash);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "MicroCore::get_tx tx does not exist in blockchain: " << tx_hash << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MicroCore::get_tx(const string& tx_hash_str, transaction& tx)
|
||||||
|
{
|
||||||
|
|
||||||
|
// parse tx hash string to hash object
|
||||||
|
crypto::hash tx_hash;
|
||||||
|
|
||||||
|
if (!xmreg::parse_str_secret_key(tx_hash_str, tx_hash))
|
||||||
|
{
|
||||||
|
cerr << "Cant parse tx hash: " << tx_hash_str << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!get_tx(tx_hash, tx))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find output with given public key in a given transaction
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
MicroCore::find_output_in_tx(const transaction& tx,
|
||||||
|
const public_key& output_pubkey,
|
||||||
|
tx_out& out,
|
||||||
|
size_t& output_index)
|
||||||
|
{
|
||||||
|
|
||||||
|
size_t idx {0};
|
||||||
|
|
||||||
|
|
||||||
|
// search in the ouputs for an output which
|
||||||
|
// public key matches to what we want
|
||||||
|
auto it = std::find_if(tx.vout.begin(), tx.vout.end(),
|
||||||
|
[&](const tx_out& o)
|
||||||
|
{
|
||||||
|
const txout_to_key& tx_in_to_key
|
||||||
|
= boost::get<txout_to_key>(o.target);
|
||||||
|
|
||||||
|
++idx;
|
||||||
|
|
||||||
|
return tx_in_to_key.key == output_pubkey;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != tx.vout.end())
|
||||||
|
{
|
||||||
|
// we found the desired public key
|
||||||
|
out = *it;
|
||||||
|
output_index = idx > 0 ? idx - 1 : idx;
|
||||||
|
|
||||||
|
//cout << idx << " " << output_index << endl;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns tx hash in a given block which
|
||||||
|
* contains given output's public key
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
MicroCore::get_tx_hash_from_output_pubkey(const public_key& output_pubkey,
|
||||||
|
const uint64_t& block_height,
|
||||||
|
crypto::hash& tx_hash,
|
||||||
|
cryptonote::transaction& tx_found)
|
||||||
|
{
|
||||||
|
|
||||||
|
tx_hash = null_hash;
|
||||||
|
|
||||||
|
// get block of given height
|
||||||
|
block blk;
|
||||||
|
if (!get_block_by_height(block_height, blk))
|
||||||
|
{
|
||||||
|
cerr << "Cant get block of height: " << block_height << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// get all transactions in the block found
|
||||||
|
// initialize the first list with transaction for solving
|
||||||
|
// the block i.e. coinbase.
|
||||||
|
list<transaction> txs {blk.miner_tx};
|
||||||
|
list<crypto::hash> missed_txs;
|
||||||
|
|
||||||
|
if (!m_blockchain_storage.get_transactions(blk.tx_hashes, txs, missed_txs))
|
||||||
|
{
|
||||||
|
cerr << "Cant find transcations in block: " << block_height << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!missed_txs.empty())
|
||||||
|
{
|
||||||
|
cerr << "Transactions not found in blk: " << block_height << endl;
|
||||||
|
|
||||||
|
for (const crypto::hash& h : missed_txs)
|
||||||
|
{
|
||||||
|
cerr << " - tx hash: " << h << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// search outputs in each transactions
|
||||||
|
// until output with pubkey of interest is found
|
||||||
|
for (const transaction& tx : txs)
|
||||||
|
{
|
||||||
|
|
||||||
|
tx_out found_out;
|
||||||
|
|
||||||
|
// we dont need here output_index
|
||||||
|
size_t output_index;
|
||||||
|
|
||||||
|
if (find_output_in_tx(tx, output_pubkey, found_out, output_index))
|
||||||
|
{
|
||||||
|
// we found the desired public key
|
||||||
|
tx_hash = get_transaction_hash(tx);
|
||||||
|
tx_found = tx;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
MicroCore::get_blk_timestamp(uint64_t blk_height)
|
||||||
|
{
|
||||||
|
cryptonote::block blk;
|
||||||
|
|
||||||
|
if (!get_block_by_height(blk_height, blk))
|
||||||
|
{
|
||||||
|
cerr << "Cant get block by height: " << blk_height << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return blk.timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-initialized Blockchain.
|
||||||
|
*
|
||||||
|
* since blockchain is opened as MDB_RDONLY
|
||||||
|
* need to manually free memory taken on heap
|
||||||
|
* by BlockchainLMDB
|
||||||
|
*/
|
||||||
|
MicroCore::~MicroCore()
|
||||||
|
{
|
||||||
|
delete &m_blockchain_storage.get_db();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
init_blockchain(const string& path,
|
||||||
|
MicroCore& mcore,
|
||||||
|
Blockchain*& core_storage)
|
||||||
|
{
|
||||||
|
|
||||||
|
// initialize the core using the blockchain path
|
||||||
|
if (!mcore.init(path))
|
||||||
|
{
|
||||||
|
cerr << "Error accessing blockchain." << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the high level Blockchain object to interact
|
||||||
|
// with the blockchain lmdb database
|
||||||
|
core_storage = &(mcore.get_core());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
MicroCore::get_blkchain_path()
|
||||||
|
{
|
||||||
|
return blockchain_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
//
|
||||||
|
// Created by mwo on 5/11/15.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef XMREG01_MICROCORE_H
|
||||||
|
#define XMREG01_MICROCORE_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "monero_headers.h"
|
||||||
|
#include "tools.h"
|
||||||
|
|
||||||
|
namespace xmreg
|
||||||
|
{
|
||||||
|
using namespace cryptonote;
|
||||||
|
using namespace crypto;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Micro version of cryptonode::core class
|
||||||
|
* Micro version of constructor,
|
||||||
|
* init and destructor are implemted.
|
||||||
|
*
|
||||||
|
* Just enough to read the blockchain
|
||||||
|
* database for use in the example.
|
||||||
|
*/
|
||||||
|
class MicroCore {
|
||||||
|
|
||||||
|
string blockchain_path;
|
||||||
|
|
||||||
|
tx_memory_pool m_mempool;
|
||||||
|
Blockchain m_blockchain_storage;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MicroCore();
|
||||||
|
|
||||||
|
bool
|
||||||
|
init(const string& _blockchain_path);
|
||||||
|
|
||||||
|
Blockchain&
|
||||||
|
get_core();
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_block_by_height(const uint64_t& height, block& blk);
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_tx(const crypto::hash& tx_hash, transaction& tx);
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_tx(const string& tx_hash, transaction& tx);
|
||||||
|
|
||||||
|
bool
|
||||||
|
find_output_in_tx(const transaction& tx,
|
||||||
|
const public_key& output_pubkey,
|
||||||
|
tx_out& out,
|
||||||
|
size_t& output_index);
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_tx_hash_from_output_pubkey(const public_key& output_pubkey,
|
||||||
|
const uint64_t& block_height,
|
||||||
|
crypto::hash& tx_hash,
|
||||||
|
transaction& tx_found);
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
get_blk_timestamp(uint64_t blk_height);
|
||||||
|
|
||||||
|
string
|
||||||
|
get_blkchain_path();
|
||||||
|
|
||||||
|
|
||||||
|
virtual ~MicroCore();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
init_blockchain(const string& path,
|
||||||
|
MicroCore& mcore,
|
||||||
|
Blockchain*& core_storage);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //XMREG01_MICROCORE_H
|
@ -0,0 +1,215 @@
|
|||||||
|
//
|
||||||
|
// Created by mwo on 8/12/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef RESTBED_XMR_YOURMONEROREQUESTS_H
|
||||||
|
#define RESTBED_XMR_YOURMONEROREQUESTS_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "tools.h"
|
||||||
|
|
||||||
|
#include "../ext/restbed/source/restbed"
|
||||||
|
|
||||||
|
namespace xmreg
|
||||||
|
{
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace restbed;
|
||||||
|
using namespace nlohmann;
|
||||||
|
|
||||||
|
|
||||||
|
string
|
||||||
|
get_current_time(const char* format = "%a, %d %b %Y %H:%M:%S %Z")
|
||||||
|
{
|
||||||
|
|
||||||
|
auto current_time = date::make_zoned(
|
||||||
|
date::current_zone(),
|
||||||
|
date::floor<chrono::seconds>(std::chrono::system_clock::now())
|
||||||
|
);
|
||||||
|
|
||||||
|
return date::format(format, current_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
multimap<string, string>
|
||||||
|
make_headers(const multimap<string, string>& extra_headers = multimap<string, string>())
|
||||||
|
{
|
||||||
|
multimap<string, string> headers {
|
||||||
|
{"Date", get_current_time()},
|
||||||
|
{"Access-Control-Allow-Origin", "http://127.0.0.1"},
|
||||||
|
{"access-control-allow-headers", "*, DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Set-Cookie"},
|
||||||
|
{"access-control-max-age", "86400, 1728000"},
|
||||||
|
{"access-control-allow-methods", "GET, POST, OPTIONS"},
|
||||||
|
{"access-control-allow-credentials", "true"},
|
||||||
|
{"Content-Type", "application/json"}
|
||||||
|
};
|
||||||
|
|
||||||
|
headers.insert(extra_headers.begin(), extra_headers.end());
|
||||||
|
|
||||||
|
return headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct handel_
|
||||||
|
{
|
||||||
|
|
||||||
|
using fetch_func_t = function< void ( const shared_ptr< Session >, const Bytes& ) >;
|
||||||
|
|
||||||
|
fetch_func_t request_callback;
|
||||||
|
|
||||||
|
handel_(const fetch_func_t& callback):
|
||||||
|
request_callback {callback}
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
void operator()(const shared_ptr< Session > session)
|
||||||
|
{
|
||||||
|
const auto request = session->get_request( );
|
||||||
|
|
||||||
|
size_t content_length = request->get_header( "Content-Length", 0);
|
||||||
|
|
||||||
|
cout << "post_get_address_info_handler" << endl;
|
||||||
|
|
||||||
|
session->fetch(content_length, this->request_callback);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class YourMoneroRequests
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static bool show_logs;
|
||||||
|
|
||||||
|
YourMoneroRequests()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void
|
||||||
|
login(const shared_ptr< Session > session, const Bytes & body)
|
||||||
|
{
|
||||||
|
json j_request = body_to_json(body);
|
||||||
|
|
||||||
|
if (show_logs)
|
||||||
|
print_json_log("login request: ", j_request);
|
||||||
|
|
||||||
|
json j_response {{"new_address", true}};
|
||||||
|
|
||||||
|
string response_body = j_response.dump();
|
||||||
|
|
||||||
|
auto response_headers = make_headers({{ "Content-Length", to_string(response_body.size())}});
|
||||||
|
|
||||||
|
session->close( OK, response_body, response_headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
get_address_txs(const shared_ptr< Session > session, const Bytes & body)
|
||||||
|
{
|
||||||
|
json j_request = body_to_json(body);
|
||||||
|
|
||||||
|
if (show_logs)
|
||||||
|
print_json_log("get_address_txs request: ", j_request);
|
||||||
|
|
||||||
|
json j_response {
|
||||||
|
{ "total_received", "0"},
|
||||||
|
{ "scanned_height", 2012455},
|
||||||
|
{ "scanned_block_height", 1195848},
|
||||||
|
{ "start_height", 2012455},
|
||||||
|
{ "transaction_height", 2012455},
|
||||||
|
{ "blockchain_height", 1195848}
|
||||||
|
};
|
||||||
|
|
||||||
|
string response_body = j_response.dump();
|
||||||
|
|
||||||
|
auto response_headers = make_headers({{ "Content-Length", to_string(response_body.size())}});
|
||||||
|
|
||||||
|
session->close( OK, response_body, response_headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
get_address_info(const shared_ptr< Session > session, const Bytes & body)
|
||||||
|
{
|
||||||
|
json j_request = body_to_json(body);
|
||||||
|
|
||||||
|
if (show_logs)
|
||||||
|
print_json_log("get_address_info request: ", j_request);
|
||||||
|
|
||||||
|
json j_response {
|
||||||
|
{"locked_funds", "0"},
|
||||||
|
{"total_received", "0"},
|
||||||
|
{"total_sent", "0"},
|
||||||
|
{"scanned_height", 2012470},
|
||||||
|
{"scanned_block_height", 1195850},
|
||||||
|
{"start_height", 2012470},
|
||||||
|
{"transaction_height", 2012470},
|
||||||
|
{"blockchain_height", 1195850},
|
||||||
|
{"spent_outputs", nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
string response_body = j_response.dump();
|
||||||
|
|
||||||
|
auto response_headers = make_headers({{ "Content-Length", to_string(response_body.size())}});
|
||||||
|
|
||||||
|
session->close( OK, response_body, response_headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<Resource>
|
||||||
|
make_resource(function< void (YourMoneroRequests&, const shared_ptr< Session >, const Bytes& ) > handle_func,
|
||||||
|
const string& path)
|
||||||
|
{
|
||||||
|
auto a_request = std::bind(handle_func, *this, std::placeholders::_1, std::placeholders::_2);
|
||||||
|
|
||||||
|
shared_ptr<Resource> resource_ptr = make_shared<Resource>();
|
||||||
|
|
||||||
|
resource_ptr->set_path(path);
|
||||||
|
resource_ptr->set_method_handler( "OPTIONS", generic_options_handler);
|
||||||
|
resource_ptr->set_method_handler( "POST" , handel_(a_request) );
|
||||||
|
|
||||||
|
return resource_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
generic_options_handler( const shared_ptr< Session > session )
|
||||||
|
{
|
||||||
|
const auto request = session->get_request( );
|
||||||
|
|
||||||
|
size_t content_length = request->get_header( "Content-Length", 0);
|
||||||
|
|
||||||
|
//cout << "generic_options_handler" << endl;
|
||||||
|
|
||||||
|
session->fetch(content_length, [](const shared_ptr< Session > session, const Bytes & body)
|
||||||
|
{
|
||||||
|
session->close( OK, string{}, make_headers());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_json_log(const string& text, const json& j)
|
||||||
|
{
|
||||||
|
cout << text << '\n' << j.dump(4) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline string
|
||||||
|
body_to_string(const Bytes & body)
|
||||||
|
{
|
||||||
|
return string(reinterpret_cast<const char *>(body.data()), body.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline json
|
||||||
|
body_to_json(const Bytes & body)
|
||||||
|
{
|
||||||
|
json j = json::parse(body_to_string(body));
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
bool YourMoneroRequests::show_logs = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //RESTBED_XMR_YOURMONEROREQUESTS_H
|
@ -0,0 +1,42 @@
|
|||||||
|
//
|
||||||
|
// Created by mwo on 5/11/15.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef XMREG01_MONERO_HEADERS_H_H
|
||||||
|
#define XMREG01_MONERO_HEADERS_H_H
|
||||||
|
|
||||||
|
#define DB_LMDB 2
|
||||||
|
#define BLOCKCHAIN_DB DB_LMDB
|
||||||
|
|
||||||
|
|
||||||
|
#define UNSIGNED_TX_PREFIX "Monero unsigned tx set\002"
|
||||||
|
#define SIGNED_TX_PREFIX "Monero signed tx set\002"
|
||||||
|
#define KEY_IMAGE_EXPORT_FILE_MAGIC "Monero key image export\002"
|
||||||
|
#define OUTPUT_EXPORT_FILE_MAGIC "Monero output export\002"
|
||||||
|
|
||||||
|
|
||||||
|
#include "net/http_base.h"
|
||||||
|
#include "net/http_server_handlers_map2.h"
|
||||||
|
#include "net/http_client.h"
|
||||||
|
#include "storages/http_abstract_invoke.h"
|
||||||
|
|
||||||
|
#include "cryptonote_core/cryptonote_basic.h"
|
||||||
|
#include "cryptonote_core/tx_pool.h"
|
||||||
|
#include "cryptonote_core/blockchain.h"
|
||||||
|
#include "blockchain_db/lmdb/db_lmdb.h"
|
||||||
|
|
||||||
|
#include "wallet/wallet2.h"
|
||||||
|
|
||||||
|
#include "serialization/binary_utils.h"
|
||||||
|
|
||||||
|
#include "ringct/rctTypes.h"
|
||||||
|
#include "ringct/rctOps.h"
|
||||||
|
#include "ringct/rctSigs.h"
|
||||||
|
|
||||||
|
#include "common/base58.h"
|
||||||
|
|
||||||
|
#include "string_coding.h"
|
||||||
|
|
||||||
|
|
||||||
|
#endif //XMREG01_MONERO_HEADERS_H_H
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,283 @@
|
|||||||
|
//
|
||||||
|
// Created by mwo on 5/11/15.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef XMREG01_TOOLS_H
|
||||||
|
#define XMREG01_TOOLS_H
|
||||||
|
|
||||||
|
#define PATH_SEPARARTOR '/'
|
||||||
|
|
||||||
|
#define XMR_AMOUNT(value) \
|
||||||
|
static_cast<double>(value) / 1e12
|
||||||
|
|
||||||
|
#define REMOVE_HASH_BRAKETS(a_hash) \
|
||||||
|
a_hash.substr(1, a_hash.size()-2)
|
||||||
|
|
||||||
|
#include "monero_headers.h"
|
||||||
|
|
||||||
|
#include "../ext/infix_iterator.h"
|
||||||
|
#include "../ext/date/tz.h"
|
||||||
|
#include "../ext/format.h"
|
||||||
|
#include "../ext/json.hpp"
|
||||||
|
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some helper functions that might or might not be useful in this project.
|
||||||
|
* Names are rather self-explanatory, so I think
|
||||||
|
* there is no reason for any detailed explanations here
|
||||||
|
*/
|
||||||
|
namespace xmreg
|
||||||
|
{
|
||||||
|
|
||||||
|
using namespace cryptonote;
|
||||||
|
using namespace crypto;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace bf = boost::filesystem;
|
||||||
|
namespace pt = boost::posix_time;
|
||||||
|
namespace gt = boost::gregorian;
|
||||||
|
namespace lt = boost::local_time;
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool
|
||||||
|
parse_str_secret_key(const string& key_str, T& secret_key);
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_tx_pub_key_from_str_hash(Blockchain& core_storage,
|
||||||
|
const string& hash_str,
|
||||||
|
transaction& tx);
|
||||||
|
|
||||||
|
bool
|
||||||
|
parse_str_address(const string& address_str,
|
||||||
|
account_public_address& address,
|
||||||
|
bool testnet = false);
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
is_separator(char c);
|
||||||
|
|
||||||
|
string
|
||||||
|
print_address(const account_public_address& address,
|
||||||
|
bool testnet = false);
|
||||||
|
|
||||||
|
string
|
||||||
|
print_sig (const signature& sig);
|
||||||
|
|
||||||
|
string
|
||||||
|
remove_trailing_path_separator(const string& in_path);
|
||||||
|
|
||||||
|
bf::path
|
||||||
|
remove_trailing_path_separator(const bf::path& in_path);
|
||||||
|
|
||||||
|
string
|
||||||
|
timestamp_to_str(time_t timestamp, const char* format = "%F %T");
|
||||||
|
|
||||||
|
string
|
||||||
|
timestamp_to_str_local(time_t timestamp, const char* format = "%F %T");
|
||||||
|
|
||||||
|
ostream&
|
||||||
|
operator<< (ostream& os, const account_public_address& addr);
|
||||||
|
|
||||||
|
|
||||||
|
string
|
||||||
|
get_default_lmdb_folder(bool testnet = false);
|
||||||
|
|
||||||
|
bool
|
||||||
|
generate_key_image(const crypto::key_derivation& derivation,
|
||||||
|
const std::size_t output_index,
|
||||||
|
const crypto::secret_key& sec_key,
|
||||||
|
const crypto::public_key& pub_key,
|
||||||
|
crypto::key_image& key_img);
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_blockchain_path(const boost::optional<string>& bc_path,
|
||||||
|
bf::path& blockchain_path,
|
||||||
|
bool testnet = false);
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
sum_money_in_outputs(const transaction& tx);
|
||||||
|
|
||||||
|
pair<uint64_t, uint64_t>
|
||||||
|
sum_money_in_outputs(const string& json_str);
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
sum_money_in_inputs(const transaction& tx);
|
||||||
|
|
||||||
|
pair<uint64_t, uint64_t>
|
||||||
|
sum_money_in_inputs(const string& json_str);
|
||||||
|
|
||||||
|
array<uint64_t, 2>
|
||||||
|
sum_money_in_tx(const transaction& tx);
|
||||||
|
|
||||||
|
array<uint64_t, 2>
|
||||||
|
sum_money_in_txs(const vector<transaction>& txs);
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
sum_fees_in_txs(const vector<transaction>& txs);
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
get_mixin_no(const transaction& tx);
|
||||||
|
|
||||||
|
vector<uint64_t>
|
||||||
|
get_mixin_no(const string& json_str);
|
||||||
|
|
||||||
|
vector<uint64_t>
|
||||||
|
get_mixin_no_in_txs(const vector<transaction>& txs);
|
||||||
|
|
||||||
|
vector<pair<txout_to_key, uint64_t>>
|
||||||
|
get_ouputs(const transaction& tx);
|
||||||
|
|
||||||
|
vector<tuple<txout_to_key, uint64_t, uint64_t>>
|
||||||
|
get_ouputs_tuple(const transaction& tx);
|
||||||
|
|
||||||
|
vector<txin_to_key>
|
||||||
|
get_key_images(const transaction& tx);
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_payment_id(const vector<uint8_t>& extra,
|
||||||
|
crypto::hash& payment_id,
|
||||||
|
crypto::hash8& payment_id8);
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_payment_id(const transaction& tx,
|
||||||
|
crypto::hash& payment_id,
|
||||||
|
crypto::hash8& payment_id8);
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
enable_monero_log() {
|
||||||
|
uint32_t log_level = 0;
|
||||||
|
epee::log_space::get_set_log_detalisation_level(true, log_level);
|
||||||
|
epee::log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline double
|
||||||
|
get_xmr(uint64_t core_amount)
|
||||||
|
{
|
||||||
|
return static_cast<double>(core_amount) / 1e12;
|
||||||
|
}
|
||||||
|
|
||||||
|
array<size_t, 5>
|
||||||
|
timestamp_difference(uint64_t t1, uint64_t t2);
|
||||||
|
|
||||||
|
string
|
||||||
|
read(string filename);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prints an iterable such as vector
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
void print_iterable(const T & elems) {
|
||||||
|
|
||||||
|
infix_ostream_iterator<typename T::value_type>
|
||||||
|
oiter(std::cout, ",");
|
||||||
|
|
||||||
|
std::cout << "[";
|
||||||
|
std::copy(elems.begin(), elems.end(),oiter);
|
||||||
|
std::cout << "]" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
pair<string, double>
|
||||||
|
timestamps_time_scale(const vector<uint64_t>& timestamps,
|
||||||
|
uint64_t timeN, uint64_t resolution = 80,
|
||||||
|
uint64_t time0 = 1397818193 /* timestamp of the second block */);
|
||||||
|
|
||||||
|
|
||||||
|
time_t
|
||||||
|
ptime_to_time_t(const pt::ptime& in_ptime);
|
||||||
|
|
||||||
|
bool
|
||||||
|
decode_ringct(const rct::rctSig & rv,
|
||||||
|
const crypto::public_key pub,
|
||||||
|
const crypto::secret_key &sec,
|
||||||
|
unsigned int i,
|
||||||
|
rct::key & mask,
|
||||||
|
uint64_t & amount);
|
||||||
|
|
||||||
|
bool
|
||||||
|
url_decode(const std::string& in, std::string& out);
|
||||||
|
|
||||||
|
map<std::string, std::string>
|
||||||
|
parse_crow_post_data(const string& req_body);
|
||||||
|
|
||||||
|
// from wallet2::decrypt
|
||||||
|
string
|
||||||
|
decrypt(const std::string &ciphertext,
|
||||||
|
const crypto::secret_key &skey,
|
||||||
|
bool authenticated = true);
|
||||||
|
|
||||||
|
// based on
|
||||||
|
// crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const
|
||||||
|
public_key
|
||||||
|
get_tx_pub_key_from_received_outs(const transaction &tx);
|
||||||
|
|
||||||
|
date::sys_seconds
|
||||||
|
parse(const std::string& str, string format="%Y-%m-%d %H:%M:%S");
|
||||||
|
|
||||||
|
static
|
||||||
|
string
|
||||||
|
xmr_amount_to_str(const uint64_t& xmr_amount, string format="{:0.12f}")
|
||||||
|
{
|
||||||
|
return fmt::format("{:0.12f}", XMR_AMOUNT(xmr_amount));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
is_output_ours(const size_t& output_index,
|
||||||
|
const transaction& tx,
|
||||||
|
const public_key& pub_tx_key,
|
||||||
|
const secret_key& private_view_key,
|
||||||
|
const public_key& public_spend_key);
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_real_output_for_key_image(const key_image& ki,
|
||||||
|
const transaction& tx,
|
||||||
|
const secret_key& private_view_key,
|
||||||
|
const public_key& public_spend_key,
|
||||||
|
uint64_t output_idx,
|
||||||
|
public_key output_pub_key);
|
||||||
|
|
||||||
|
// based on http://stackoverflow.com/a/9943098/248823
|
||||||
|
template<typename Iterator, typename Func>
|
||||||
|
void chunks(Iterator begin,
|
||||||
|
Iterator end,
|
||||||
|
iterator_traits<string::iterator>::difference_type k,
|
||||||
|
Func f)
|
||||||
|
{
|
||||||
|
Iterator chunk_begin;
|
||||||
|
Iterator chunk_end;
|
||||||
|
chunk_end = chunk_begin = begin;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(std::distance(chunk_end, end) < k)
|
||||||
|
chunk_end = end;
|
||||||
|
else
|
||||||
|
std::advance(chunk_end, k);
|
||||||
|
f(chunk_begin,chunk_end);
|
||||||
|
chunk_begin = chunk_end;
|
||||||
|
}
|
||||||
|
while(std::distance(chunk_begin,end) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
make_tx_from_json(const string& json_str, transaction& tx);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //XMREG01_TOOLS_H
|
Loading…
Reference in new issue