oxen-core/src/wallet3/wallet.cpp

174 lines
3.9 KiB
C++

#include "wallet.hpp"
#include "db_schema.hpp"
#include "wallet2½.hpp"
#include "block.hpp"
#include "block_tx.hpp"
#include "default_daemon_comms.hpp"
#include <common/hex.h>
#include <cryptonote_basic/cryptonote_basic.h>
#include <sqlitedb/database.hpp>
#include <oxenmq/oxenmq.h>
#include "common/fs.h"
#include <future>
#include <chrono>
#include <thread>
#include <iostream>
namespace wallet
{
Wallet::Wallet(
std::shared_ptr<oxenmq::OxenMQ> omq,
std::shared_ptr<Keyring> keys,
std::shared_ptr<TransactionConstructor> tx_constructor,
std::shared_ptr<DaemonComms> daemon_comms,
std::string_view dbFilename,
std::string_view dbPassword,
wallet::Config config_in)
: omq(omq)
, db{std::make_shared<WalletDB>(fs::path(dbFilename), dbPassword)}
, keys{keys}
, tx_scanner{keys, db}
, tx_constructor{tx_constructor}
, daemon_comms{daemon_comms}
, omq_server{request_handler}
, config(config_in)
{
if (not omq)
this->omq = std::make_shared<oxenmq::OxenMQ>();
if (not daemon_comms)
this->daemon_comms = std::make_shared<DefaultDaemonComms>(omq, config.daemon);
if (not tx_constructor)
this->tx_constructor = std::make_shared<TransactionConstructor>(db, daemon_comms);
omq_server.set_omq(this->omq, config.omq_rpc);
db->create_schema();
db->add_address(0, 0, keys->get_main_address());
last_scan_height = db->last_scan_height();
scan_target_height = db->scan_target_height();
}
void
Wallet::init()
{
request_handler.set_wallet(weak_from_this());
omq->start();
daemon_comms->set_remote(config.daemon.address);
daemon_comms->register_wallet(*this, last_scan_height + 1 /*next needed block*/,
true /* update sync height */,
true /* new wallet */);
}
Wallet::~Wallet()
{
}
void
Wallet::propogate_config()
{
daemon_comms->propogate_config();
}
uint64_t
Wallet::get_balance()
{
return db->overall_balance();
}
uint64_t
Wallet::get_unlocked_balance()
{
return 0; // TODO: this
}
cryptonote::account_keys
Wallet::export_keys()
{
return keys->export_keys();
};
void
Wallet::add_block(const Block& block)
{
auto db_tx = db->db_transaction();
db->store_block(block);
for (const auto& tx : block.transactions)
{
if (auto outputs = tx_scanner.scan_received(tx, block.height, block.timestamp);
not outputs.empty())
{
db->store_transaction(tx.hash, block.height, outputs);
}
if (auto spends = tx_scanner.scan_spent(tx.tx); not spends.empty())
{
db->store_spends(tx.hash, block.height, spends);
}
}
db_tx.commit();
last_scan_height++;
}
void
Wallet::add_blocks(const std::vector<Block>& blocks)
{
if (not running)
return;
if (blocks.size() == 0)
//TODO: error handling; this shouldn't be able to happen
return;
if (blocks.front().height > last_scan_height + 1)
{
daemon_comms->register_wallet(*this, last_scan_height + 1 /*next needed block*/, true);
return;
}
for (const auto& block : blocks)
{
if (block.height == last_scan_height + 1)
add_block(block);
}
daemon_comms->register_wallet(*this, last_scan_height + 1 /*next needed block*/, false);
}
void
Wallet::update_top_block_info(int64_t height, const crypto::hash& hash)
{
if (not running)
return;
db->update_top_block_info(height, hash);
scan_target_height = height;
}
void
Wallet::deregister()
{
running = false;
auto self = weak_from_this();
std::promise<void> p;
auto f = p.get_future();
daemon_comms->deregister_wallet(*this, p);
f.wait();
/*
// At this point, only the true "owner" should have a reference
using namespace std::chrono_literals;
while (self.use_count() > 1)
std::this_thread::sleep_for(50ms);
*/
}
} // namespace wallet