1
0
Fork 0
forked from lthn/blockchain

Merge branch 'develop_mobile' into wallet_crypt

This commit is contained in:
cryptozoidberg 2020-07-17 23:54:10 +02:00
commit ea07ed3e17
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
37 changed files with 574 additions and 268 deletions

View file

@ -153,7 +153,8 @@ else()
set(DEBUG_FLAGS "-g3 -O0")
endif()
set(RELEASE_FLAGS "-Ofast -DNDEBUG -Wno-unused-variable")
if(NOT APPLE)
if(NOT APPLE AND NOT (CMAKE_SYSTEM_NAME STREQUAL "Android"))
set(RELEASE_FLAGS "${RELEASE_FLAGS} -flto")
endif()
#if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT MINGW)

View file

@ -608,7 +608,8 @@ POP_GCC_WARNINGS
t_pod_type hex_to_pod(const std::string& hex_str)
{
t_pod_type p = AUTO_VAL_INIT(p);
hex_to_pod(hex_str, p);
if (!hex_to_pod(hex_str, p))
return AUTO_VAL_INIT_T(t_pod_type);
return p;
}
//----------------------------------------------------------------------------

View file

@ -21,6 +21,7 @@
#define API_RETURN_CODE_WRONG_PASSWORD "WRONG_PASSWORD"
#define API_RETURN_CODE_WALLET_WRONG_ID "WALLET_WRONG_ID"
#define API_RETURN_CODE_WALLET_WATCH_ONLY_NOT_SUPPORTED "WALLET_WATCH_ONLY_NOT_SUPPORTED"
#define API_RETURN_CODE_WALLET_AUDITABLE_NOT_SUPPORTED "WALLET_AUDITABLE_NOT_SUPPORTED"
#define API_RETURN_CODE_FILE_NOT_FOUND "FILE_NOT_FOUND"
#define API_RETURN_CODE_ALREADY_EXISTS "ALREADY_EXISTS"
#define API_RETURN_CODE_CANCELED "CANCELED"

View file

@ -695,4 +695,60 @@ std::string get_nix_version_display_string()
return true;
}
//this code was taken from https://stackoverflow.com/a/8594696/5566653
//credits goes to @nijansen: https://stackoverflow.com/users/1056003/nijansen
bool copy_dir( boost::filesystem::path const & source, boost::filesystem::path const & destination)
{
namespace fs = boost::filesystem;
try
{
// Check whether the function call is valid
if (!fs::exists(source) ||!fs::is_directory(source))
{
LOG_ERROR("Source directory " << source.string() << " does not exist or is not a directory.");
return false;
}
if (!fs::exists(destination))
{
if (!fs::create_directory(destination))
{
LOG_ERROR("Unable to create destination directory" << destination.string());
return false;
}
}
// Create the destination directory
}
catch (fs::filesystem_error const & e)
{
LOG_ERROR("Exception: " << e.what());
return false;
}
// Iterate through the source directory
for (fs::directory_iterator file(source); file != fs::directory_iterator(); ++file)
{
try
{
fs::path current(file->path());
if (fs::is_directory(current))
{
// Found directory: Recursion
if (!copy_dir(current, destination / current.filename()))
{
return false;
}
}
else
{
// Found file: Copy
fs::copy_file( current, destination / current.filename());
}
}
catch (fs::filesystem_error const & e)
{
LOG_ERROR("Exception: " << e.what());
}
}
return true;
}
} // namespace tools

View file

@ -23,6 +23,12 @@
#include <dbghelp.h>
#endif
#ifdef NDEBUG
#define BUILD_TYPE "Release"
#else
#define BUILD_TYPE "Debug"
#endif
namespace tools
{
std::string get_host_computer_name();
@ -30,6 +36,7 @@ namespace tools
std::string get_default_user_dir();
std::string get_current_username();
std::string get_os_version_string();
bool copy_dir(boost::filesystem::path const & source, boost::filesystem::path const & destination);
bool check_remote_client_version(const std::string& client_ver);
bool create_directories_if_necessary(const std::string& path);

View file

@ -91,6 +91,9 @@ namespace bc_services
}
#define CURRENCY_CPD_ARCHIVE_VER 1
BOOST_CLASS_VERSION(bc_services::contract_private_details, CURRENCY_CPD_ARCHIVE_VER)
namespace boost
{
namespace serialization
@ -100,8 +103,20 @@ namespace boost
{
ar & cpd.title;
ar & cpd.comment;
ar & cpd.a_addr; // usually buyer
ar & cpd.b_addr; // usually seller
if (version == 0 && !archive_t::is_saving::value)
{
// loading from version 0 (pre-auditable address format)
currency::account_public_address_old old_addr = AUTO_VAL_INIT(old_addr);
ar & old_addr;
cpd.a_addr = currency::account_public_address::from_old(old_addr);
ar & old_addr;
cpd.b_addr = currency::account_public_address::from_old(old_addr);
}
else
{
ar & cpd.a_addr; // usually buyer
ar & cpd.b_addr; // usually seller
}
ar & cpd.amount_to_pay;
ar & cpd.amount_a_pledge;
ar & cpd.amount_b_pledge;

View file

@ -305,12 +305,19 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
LOG_PRINT_MAGENTA("Migrating DB: " << m_db_storage_major_compatibility_version << " -> " << BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION, LOG_LEVEL_0);
res = m_db_aliases.deinit();
CHECK_AND_ASSERT_MES(res, false, "Unable to deinit db container");
CHECK_AND_ASSERT_MES(res, false, "Unable to deinit m_db_aliases");
res = m_db_addr_to_alias.deinit();
CHECK_AND_ASSERT_MES(res, false, "Unable to deinit m_db_addr_to_alias");
typedef tools::db::cached_key_value_accessor<std::string, std::list<extra_alias_entry_base_old>, true, true> aliases_container_old;
aliases_container_old db_aliases_old(m_db);
res = db_aliases_old.init(BLOCKCHAIN_STORAGE_CONTAINER_ALIASES);
CHECK_AND_ASSERT_MES(res, false, "Unable to init db container");
CHECK_AND_ASSERT_MES(res, false, "Unable to init db_aliases_old");
typedef tools::db::cached_key_value_accessor<account_public_address_old, std::set<std::string>, true, false> address_to_aliases_container_old;
address_to_aliases_container_old db_addr_to_alias_old(m_db);
res = db_addr_to_alias_old.init(BLOCKCHAIN_STORAGE_CONTAINER_ADDR_TO_ALIAS);
CHECK_AND_ASSERT_MES(res, false, "Unable to init db_addr_to_alias_old");
// temporary set db compatibility version to zero during migration in order to trigger db reinit on the next lanunch in case the process stops in the middle
m_db.begin_transaction();
@ -329,19 +336,33 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
return true;
});
typedef std::vector<std::pair<account_public_address, std::set<std::string>>> add_to_alias_container_t;
add_to_alias_container_t addr_to_alias_container;
db_addr_to_alias_old.enumerate_items([&addr_to_alias_container](uint64_t n, const account_public_address_old& addr_old, const std::set<std::string>& aliases){
addr_to_alias_container.emplace_back(std::make_pair(account_public_address::from_old(addr_old), aliases));
return true;
});
// clear and close old format container
m_db.begin_transaction();
db_aliases_old.clear();
db_addr_to_alias_old.clear();
m_db.commit_transaction();
db_aliases_old.deinit();
db_addr_to_alias_old.deinit();
res = m_db_aliases.init(BLOCKCHAIN_STORAGE_CONTAINER_ALIASES);
CHECK_AND_ASSERT_MES(res, false, "Unable to init db container");
CHECK_AND_ASSERT_MES(res, false, "Unable to init m_db_aliases");
res = m_db_addr_to_alias.init(BLOCKCHAIN_STORAGE_CONTAINER_ADDR_TO_ALIAS);
CHECK_AND_ASSERT_MES(res, false, "Unable to init m_db_addr_to_alias");
// re-populate all alias entries back
m_db.begin_transaction();
for(auto& el : temp_container)
m_db_aliases.set(el.first, el.second);
for(auto& el : addr_to_alias_container)
m_db_addr_to_alias.set(el.first, el.second);
m_db.commit_transaction();
// restore db maj compartibility
@ -3511,6 +3532,20 @@ bool blockchain_storage::put_alias_info(const transaction & tx, extra_alias_entr
else
{
LOG_ERROR("Wrong m_addr_to_alias state: address not found " << get_account_address_as_str(local_alias_history.back().m_address));
std::stringstream ss;
ss << "History for alias " << ai.m_alias << ":" << ENDL;
size_t i = 0;
for (auto el : local_alias_history)
{
ss << std::setw(2) << i++ << " "
<< get_account_address_as_str(el.m_address) << " "
<< (el.m_sign.empty() ? " no sig " : " SIGNED ") << " "
<< el.m_text_comment << ENDL;
}
LOG_PRINT_L0(ss.str());
}
//update alias db

View file

@ -36,15 +36,5 @@ namespace boost
ar & ei.stake_hash;
}
template<class archive_t>
void serialize(archive_t & ar, currency::extra_alias_entry_base& ai, const unsigned int version)
{
ar & ai.m_address.spend_public_key;
ar & ai.m_address.view_public_key;
ar & ai.m_view_key;
ar & ai.m_sign;
ar & ai.m_text_comment;
//ar & ai.;
}
}
}

View file

@ -711,6 +711,7 @@ namespace currency
} // namespace currency
POD_MAKE_HASHABLE(currency, account_public_address);
POD_MAKE_HASHABLE(currency, account_public_address_old);
BLOB_SERIALIZER(currency::txout_to_key);

View file

@ -31,13 +31,14 @@ namespace currency
{
//-----------------------------------------------------------------------------------------------
core::core(i_currency_protocol* pprotocol):
m_mempool(m_blockchain_storage, pprotocol),
m_blockchain_storage(m_mempool),
m_miner(this, m_blockchain_storage),
m_miner_address(boost::value_initialized<account_public_address>()),
m_starter_message_showed(false),
m_critical_error_handler(nullptr)
core::core(i_currency_protocol* pprotocol)
: m_mempool(m_blockchain_storage, pprotocol)
, m_blockchain_storage(m_mempool)
, m_miner(this, m_blockchain_storage)
, m_miner_address(boost::value_initialized<account_public_address>())
, m_starter_message_showed(false)
, m_critical_error_handler(nullptr)
, m_stop_after_height(0)
{
set_currency_protocol(pprotocol);
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -50,8 +50,8 @@ export class InputValidateDirective {
}
currentValue = _zero_fill.join('.');
if (currentValue !== originalValue) {
const cursorPosition = (<HTMLInputElement>event.target).selectionEnd;
(<HTMLInputElement>event.target).value = currentValue;
const cursorPosition = (<HTMLInputElement>event.target).selectionEnd;
(<HTMLInputElement>event.target).setSelectionRange(cursorPosition, cursorPosition);
(<HTMLInputElement>event.target).dispatchEvent(new Event('input'));
}

View file

@ -1,3 +1,3 @@
export const MIXIN: number = 10;
export const AUDITABLE_WALLET_HELP_PAGE: string = 'zano.org';
export const AUDITABLE_WALLET_HELP_PAGE: string = 'docs.zano.org/docs/auditable-wallets';
export const RCV_ADDR_QR_SCALE: number = 2;

View file

@ -60,7 +60,9 @@ export class LoginComponent implements OnInit, OnDestroy {
this.backend.storeSecureAppData({pass: this.variablesService.appPass});
this.variablesService.appLogin = true;
this.variablesService.dataIsLoaded = true;
this.variablesService.startCountdown();
if (this.variablesService.settings.appLockTime) {
this.variablesService.startCountdown();
}
this.ngZone.run(() => {
this.router.navigate(['/']);
});
@ -95,7 +97,9 @@ export class LoginComponent implements OnInit, OnDestroy {
this.backend.checkMasterPassword({pass: this.variablesService.appPass}, (status, data) => {
if (status) {
this.variablesService.appLogin = true;
this.variablesService.startCountdown();
if (this.variablesService.settings.appLockTime) {
this.variablesService.startCountdown();
}
this.ngZone.run(() => {
this.router.navigate(['/']);
});
@ -112,7 +116,9 @@ export class LoginComponent implements OnInit, OnDestroy {
if (!data.error_code) {
this.variablesService.appLogin = true;
this.variablesService.dataIsLoaded = true;
this.variablesService.startCountdown();
if (this.variablesService.settings.appLockTime) {
this.variablesService.startCountdown();
}
this.variablesService.appPass = appPass;
const isEmptyObject = Object.keys(data).length === 0 && data.constructor === Object;

View file

@ -6,7 +6,7 @@
<div class="message-container">
<div class="message-block">
<div class="message-label">{{ 'CONFIRM.MESSAGE.SEND' | translate }}</div>
<div class="message-text">{{ form.get('amount').value }} {{variablesService.defaultCurrency}}</div>
<div class="message-text">{{ +form.get('amount').value }} {{variablesService.defaultCurrency}}</div>
</div>
<div class="message-block">
<div class="message-label">{{ 'CONFIRM.MESSAGE.FROM' | translate }}</div>
@ -20,8 +20,8 @@
<div class="message-block" *ngIf="form.get('comment').value != null">
<div class="message-label">{{ 'CONFIRM.MESSAGE.COMMENT' | translate }}</div>
<div class="message-text">{{ form.get('comment').value }}</div>
</div>
</ng-container>
</div>
</ng-container>
</div>
</div>
<div class="wrapper-buttons">

View file

@ -153,7 +153,9 @@ export class SettingsComponent implements OnInit {
this.backend.storeSecureAppData({pass: this.variablesService.appPass});
this.variablesService.appLogin = true;
this.variablesService.dataIsLoaded = true;
this.variablesService.startCountdown();
if (this.variablesService.settings.appLockTime) {
this.variablesService.startCountdown();
}
} else {
console.log(data['error_code']);
}
@ -166,7 +168,7 @@ export class SettingsComponent implements OnInit {
}
onLockChange() {
if (this.variablesService.appLogin) {
if (this.variablesService.appLogin && this.variablesService.settings.appLockTime) {
this.variablesService.restartCountdown();
}
this.backend.storeAppData();

View file

@ -5,19 +5,14 @@
<div class="sidebar-accounts-list scrolled-content">
<div class="sidebar-account" *ngFor="let wallet of variablesService.wallets" [class.active]="wallet?.wallet_id === walletActive" [routerLink]="['/wallet/' + wallet.wallet_id + '/history']">
<div class="wallet-type" (click)="goToAuditableWalletHelpPage($event)">
<div class="auditable" *ngIf="wallet.is_auditable && !wallet.is_watch_only">
<div class="content">Auditable</div>
<div class="content auditable" *ngIf="wallet.is_auditable && !wallet.is_watch_only">
Auditable
</div>
<div class="watch-only" *ngIf="!wallet.is_auditable && wallet.is_watch_only">
<div class="content">Watch-only</div>
<div class="content watch-only" *ngIf="!wallet.is_auditable && wallet.is_watch_only">
Watch-only
</div>
<div class="auditable-watch-only" *ngIf="wallet.is_auditable && wallet.is_watch_only">
<div>
<div class="content">Auditable</div>
</div>
<div>
<div class="content">Watch-only</div>
</div>
<div class="content auditable-watch-only" *ngIf="wallet.is_auditable && wallet.is_watch_only">
Auditable Watch-Only
</div>
</div>
<div class="close-wallet-wrapper">

View file

@ -27,73 +27,31 @@
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 7px;
width: 7px;
height: 100%;
background-color: transparent;
transition: all ease .3s;
> div {
height: 100%;
width: 100%;
}
overflow: hidden;
&:hover {
height: auto;
.content {
opacity: 1;
}
.auditable {
background-color: transparent;
.content {
margin: 0 3rem;
background-color: #5cda9d;
}
}
.watch-only {
background-color: transparent;
.content {
margin: 0 3rem;
background-color: #8686ff;
}
}
.auditable-watch-only {
> div:first-child {
margin-right: 10px;
margin-left: 3rem;
}
> div:last-child {
margin-right: 3rem;
}
}
width: 28px;
}
.content {
padding: 5px;
height: 100%;
padding: 7px;
font-size: 12px;
text-align: center;
color: #000000;
line-height: 14px;
font-weight: 500;
color: #ffffff;
text-decoration: none;
text-transform: capitalize;
transition: all ease .3s;
opacity: 0;
}
.auditable {
background-color: #5cda9d;
}
.watch-only {
background-color: #8686ff;
}
.auditable-watch-only {
display: flex;
> div {
transition: all ease .3s;
width: 100%;
.content {
transition: none;
}
&:first-child {
background-color: #5cda9d;
}
&:last-child {
background-color: #8686ff;
}
writing-mode: vertical-rl;
text-orientation: mixed;
&.auditable {
background-color: #5cda9d;
}
&.watch-only, &.auditable-watch-only {
background-color: #8686ff;
}
}
}
@ -135,7 +93,7 @@
flex-direction: column;
flex-shrink: 0;
cursor: pointer;
padding: 2rem 3rem;
padding: 2.5rem 3rem;
.close-wallet-wrapper {
display: flex;
@ -144,8 +102,8 @@
button {
display: flex;
position: absolute;
top: 6px;
right: -20px;
top: -12px;
right: -18px;
padding: 0;
height: auto;
background: transparent;

View file

@ -52,7 +52,6 @@ namespace
const command_line::arg_descriptor<bool> arg_do_pos_mining = { "do-pos-mining", "Do PoS mining", false, false };
const command_line::arg_descriptor<std::string> arg_pos_mining_reward_address = { "pos-mining-reward-address", "Block reward will be sent to the giving address if specified", "" };
const command_line::arg_descriptor<std::string> arg_restore_wallet = { "restore-wallet", "Restore wallet from the seed phrase and save it to <arg>", "" };
const command_line::arg_descriptor<std::string> arg_restore_awo_wallet = { "restore-awo-wallet", "Restore auditable watch-only wallet from address and view key. Use \"address:viewkey\" as argument", "" };
const command_line::arg_descriptor<bool> arg_offline_mode = { "offline-mode", "Don't connect to daemon, work offline (for cold-signing process)", false, true };
const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""};
@ -274,7 +273,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
return false;
}
if (m_wallet_file.empty() && m_generate_new.empty() && m_restore_wallet.empty() && m_restore_awo_wallet.empty() && m_generate_new_aw.empty())
if (m_wallet_file.empty() && m_generate_new.empty() && m_restore_wallet.empty() && m_generate_new_aw.empty())
{
fail_msg_writer() << "you must specify --wallet-file, --generate-new-wallet, --generate-new-auditable-wallet, --restore-wallet or --restore-awo-wallet";
return false;
@ -332,31 +331,14 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
}
tools::password_container restore_seed_container;
if (!restore_seed_container.read_password("please, enter wallet seed phrase:\n"))
{
fail_msg_writer() << "failed to read seed phrase";
return false;
}
bool r = restore_wallet(m_restore_wallet, restore_seed_container.password(), pwd_container.password(), false);
CHECK_AND_ASSERT_MES(r, false, "wallet restoring failed");
}
else if (!m_restore_awo_wallet.empty())
{
if (boost::filesystem::exists(m_restore_awo_wallet))
{
fail_msg_writer() << "file " << m_restore_awo_wallet << " already exists";
return false;
}
tools::password_container restore_addr_and_viewkey_container;
if (!restore_addr_and_viewkey_container.read_password("please, enter wallet auditable address, viewkey and timestamp, separated by a colon (\"address:viewkey:timestamp\"):\n"))
if (!restore_seed_container.read_password("please, enter wallet seed phrase or an auditable wallet tracking key:\n"))
{
fail_msg_writer() << "failed to read seed phrase";
return false;
}
bool r = restore_wallet(m_restore_awo_wallet, restore_addr_and_viewkey_container.password(), pwd_container.password(), true);
bool looks_like_tracking_seed = restore_seed_container.password().find(':') != std::string::npos;
bool r = restore_wallet(m_restore_wallet, restore_seed_container.password(), pwd_container.password(), looks_like_tracking_seed);
CHECK_AND_ASSERT_MES(r, false, "wallet restoring failed");
}
else
@ -387,7 +369,6 @@ void simple_wallet::handle_command_line(const boost::program_options::variables_
m_do_not_set_date = command_line::get_arg(vm, arg_dont_set_date);
m_do_pos_mining = command_line::get_arg(vm, arg_do_pos_mining);
m_restore_wallet = command_line::get_arg(vm, arg_restore_wallet);
m_restore_awo_wallet = command_line::get_arg(vm, arg_restore_awo_wallet);
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::try_connect_to_daemon()
@ -1778,7 +1759,6 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_do_pos_mining);
command_line::add_arg(desc_params, arg_pos_mining_reward_address);
command_line::add_arg(desc_params, arg_restore_wallet);
command_line::add_arg(desc_params, arg_restore_awo_wallet);
command_line::add_arg(desc_params, arg_offline_mode);
command_line::add_arg(desc_params, command_line::arg_log_file);
command_line::add_arg(desc_params, command_line::arg_log_level);

View file

@ -167,7 +167,6 @@ namespace currency
bool m_do_pos_mining;
bool m_offline_mode;
std::string m_restore_wallet;
std::string m_restore_awo_wallet;
epee::console_handlers_binder m_cmd_binder;

View file

@ -8,6 +8,6 @@
#define PROJECT_REVISION "7"
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
#define PROJECT_VERSION_BUILD_NO 92
#define PROJECT_VERSION_BUILD_NO 95
#define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO)
#define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]"

View file

@ -145,8 +145,8 @@ namespace tools
bool r = m_http_client.connect(u.host, std::to_string(u.port), m_connection_timeout);
if (r)
{
*m_plast_daemon_is_disconnected = false;
m_last_success_interract_time = time(nullptr);
m_pdiganostic_info->last_daemon_is_disconnected = false;
m_pdiganostic_info->last_success_interract_time = time(nullptr);
}
return r;
}
@ -177,11 +177,11 @@ namespace tools
return tools::get_transfer_address(adr_str, addr, payment_id, this);
}
//------------------------------------------------------------------------------------------------------------------------------
void default_http_core_proxy::set_plast_daemon_is_disconnected(std::atomic<bool> *plast_daemon_is_disconnected)
{
CRITICAL_REGION_LOCAL(m_lock);
m_plast_daemon_is_disconnected = plast_daemon_is_disconnected ? plast_daemon_is_disconnected : &m_last_daemon_is_disconnected_stub;
}
// void default_http_core_proxy::set_plast_daemon_is_disconnected(std::atomic<bool> *plast_daemon_is_disconnected)
// {
// CRITICAL_REGION_LOCAL(m_lock);
// m_plast_daemon_is_disconnected = plast_daemon_is_disconnected ? plast_daemon_is_disconnected : &m_last_daemon_is_disconnected_stub;
// }
//------------------------------------------------------------------------------------------------------------------------------
bool default_http_core_proxy::set_connectivity(unsigned int connection_timeout, size_t repeats_count)
{
@ -190,8 +190,8 @@ namespace tools
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
default_http_core_proxy::default_http_core_proxy() :m_plast_daemon_is_disconnected(&m_last_daemon_is_disconnected_stub),
m_last_success_interract_time(0),
default_http_core_proxy::default_http_core_proxy(): //:m_plast_daemon_is_disconnected(&m_last_daemon_is_disconnected_stub),
//m_last_success_interract_time(0),
m_connection_timeout(WALLET_RCP_CONNECTION_TIMEOUT),
m_attempts_count(WALLET_RCP_COUNT_ATTEMNTS)
{

View file

@ -69,11 +69,11 @@ namespace tools
if (ret)
{
m_last_success_interract_time = time(nullptr);
*m_plast_daemon_is_disconnected = false;
m_pdiganostic_info->last_success_interract_time = time(nullptr);
m_pdiganostic_info->last_daemon_is_disconnected = false;
}
else
*m_plast_daemon_is_disconnected = true;
m_pdiganostic_info->last_daemon_is_disconnected = true;
return ret;
}
@ -124,15 +124,13 @@ namespace tools
//------------------------------------------------------------------------------------------------------------------------------
virtual time_t get_last_success_interract_time() override
{
return m_last_success_interract_time;
return m_pdiganostic_info->last_success_interract_time;
}
epee::critical_section m_lock;
epee::net_utils::http::http_simple_client m_http_client;
std::string m_daemon_address;
std::atomic<time_t> m_last_success_interract_time;
std::atomic<bool> *m_plast_daemon_is_disconnected;
std::atomic<bool> m_last_daemon_is_disconnected_stub;
unsigned int m_connection_timeout;
size_t m_attempts_count;

View file

@ -11,6 +11,15 @@
namespace tools
{
struct proxy_diagnostic_info
{
proxy_diagnostic_info():is_busy(false), last_success_interract_time(0), last_daemon_is_disconnected(0)
{}
std::atomic<bool> is_busy;
std::atomic<time_t> last_success_interract_time;
std::atomic<bool> last_daemon_is_disconnected;
};
/*
wrapper to core api (rpc/direct call)
*/
@ -44,10 +53,18 @@ namespace tools
virtual bool call_COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN(const currency::COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::request& req, currency::COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::response& res){ return false; }
virtual bool call_COMMAND_RPC_GET_POOL_INFO(const currency::COMMAND_RPC_GET_POOL_INFO::request& req, currency::COMMAND_RPC_GET_POOL_INFO::response& res) { return false; }
i_core_proxy()
{
m_pdiganostic_info.reset(new proxy_diagnostic_info());
}
virtual bool check_connection(){ return false; }
virtual time_t get_last_success_interract_time() { return 0; }
std::shared_ptr<const proxy_diagnostic_info> get_proxy_diagnostic_info() const { return m_pdiganostic_info; }
std::shared_ptr<proxy_diagnostic_info> get_editable_proxy_diagnostic_info() { return m_pdiganostic_info; }
virtual bool get_transfer_address(const std::string& adr_str, currency::account_public_address& addr, std::string& payment_id){ return false; }
protected:
std::shared_ptr<proxy_diagnostic_info> m_pdiganostic_info;
};
}

View file

@ -187,7 +187,6 @@ namespace plain_wallet
epee::static_helpers::set_or_call_on_destruct(true, static_destroy_handler);
std::cout << "[INIT PLAIN_WALLET_INSTANCE]" << ENDL;
std::shared_ptr<plain_wallet_instance> ptr(new plain_wallet_instance());
set_bundle_working_dir(working_dir);
@ -208,13 +207,15 @@ namespace plain_wallet
}
ptr->gwm.set_use_deffered_global_outputs(true);
if(!ptr->gwm.start())
{
LOG_ERROR("Failed to start wallets_manager");
return GENERAL_INTERNAL_ERRROR_INIT;
}
LOG_PRINT_L0("[INIT PLAIN_WALLET_INSTANCE] Ver:" << PROJECT_VERSION_LONG << "(" << BUILD_TYPE << ")");
std::string wallets_folder = get_wallets_folder();
boost::system::error_code ec;
boost::filesystem::create_directories(wallets_folder, ec);
@ -324,6 +325,31 @@ namespace plain_wallet
return epee::serialization::store_t_to_json(sl);
}
std::string get_export_private_info(const std::string& target_dir)
{
const std::string src_folder_path = get_bundle_working_dir();
boost::system::error_code ec;
const std::string full_target_path = target_dir + "/Zano_export" + std::to_string(epee::misc_utils::get_tick_count());
boost::filesystem::create_directory(full_target_path, ec);
if (ec)
{
LOG_ERROR("Failed to create target directory(" << full_target_path << "):" << ec.message());
epee::json_rpc::response<view::api_responce_return_code, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
ok_response.result.return_code = API_RETURN_CODE_FAIL;
return epee::serialization::store_t_to_json(ok_response);
}
if(!tools::copy_dir(src_folder_path, full_target_path))
{
LOG_ERROR("Failed to copy target directory");
epee::json_rpc::response<view::api_responce_return_code, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
ok_response.result.return_code = API_RETURN_CODE_FAIL;
return epee::serialization::store_t_to_json(ok_response);
}
epee::json_rpc::response<view::api_responce_return_code, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
ok_response.result.return_code = API_RETURN_CODE_OK;
return epee::serialization::store_t_to_json(ok_response);
}
std::string delete_wallet(const std::string& file_name)
{
std::string wallet_files_path = get_wallets_folder();

View file

@ -15,6 +15,7 @@ namespace plain_wallet
std::string set_log_level(int log_level);
std::string get_version();
std::string get_wallet_files();
std::string get_export_private_info(const std::string& target_dir);
std::string delete_wallet(const std::string& file_name);
std::string get_address_info(const std::string& addr);

View file

@ -467,10 +467,12 @@ public:
{
bool is_online;
bool last_daemon_is_disconnected;
bool is_server_busy;
uint64_t last_proxy_communicate_timestamp;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(is_online)
KV_SERIALIZE(is_server_busy)
KV_SERIALIZE(last_daemon_is_disconnected)
KV_SERIALIZE(last_proxy_communicate_timestamp)
END_KV_SERIALIZE_MAP()

View file

@ -1339,6 +1339,8 @@ void wallet2::pull_blocks(size_t& blocks_added, std::atomic<bool>& stop)
req.minimum_height = get_wallet_minimum_height();
if (is_auditable())
req.need_global_indexes = true;
if (req.minimum_height > m_height_of_start_sync)
m_height_of_start_sync = req.minimum_height;
m_chain.get_short_chain_history(req.block_ids);
bool r = m_core_proxy->call_COMMAND_RPC_GET_BLOCKS_DIRECT(req, res);
@ -1370,9 +1372,11 @@ void wallet2::pull_blocks(size_t& blocks_added, std::atomic<bool>& stop)
if (res.status == API_RETURN_CODE_BUSY)
{
WLT_LOG_L1("Core is busy, pull cancelled");
m_core_proxy->get_editable_proxy_diagnostic_info()->is_busy = true;
stop = true;
return;
}
m_core_proxy->get_editable_proxy_diagnostic_info()->is_busy = false;
THROW_IF_TRUE_WALLET_EX(res.status != API_RETURN_CODE_OK, error::get_blocks_error, res.status);
THROW_IF_TRUE_WALLET_EX(get_blockchain_current_size() && get_blockchain_current_size() <= res.start_height && res.start_height != m_minimum_height, error::wallet_internal_error,
"wrong daemon response: m_start_height=" + std::to_string(res.start_height) +
@ -1500,6 +1504,7 @@ void wallet2::refresh()
void wallet2::refresh(size_t & blocks_fetched)
{
bool received_money = false;
m_stop = false;
refresh(blocks_fetched, received_money, m_stop);
}
//----------------------------------------------------------------------------------------------------

View file

@ -663,13 +663,13 @@ namespace tools
// do not load wallet if data version is greather than the code version
if (ver > WALLET_FILE_SERIALIZATION_VERSION)
{
LOG_PRINT_MAGENTA("Wallet file truncated due to WALLET_FILE_SERIALIZATION_VERSION is more then curren build", LOG_LEVEL_0);
WLT_LOG_MAGENTA("Wallet file truncated due to WALLET_FILE_SERIALIZATION_VERSION is more then curren build", LOG_LEVEL_0);
return;
}
if (ver < 149)
{
LOG_PRINT_MAGENTA("Wallet file truncated due to old version", LOG_LEVEL_0);
WLT_LOG_MAGENTA("Wallet file truncated due to old version", LOG_LEVEL_0);
return;
}
@ -684,14 +684,14 @@ namespace tools
a & formation_ver;
if (formation_ver != CURRENCY_FORMATION_VERSION)
{
LOG_PRINT_MAGENTA("Wallet file truncated due to mismatch CURRENCY_FORMATION_VERSION", LOG_LEVEL_0);
WLT_LOG_MAGENTA("Wallet file truncated due to mismatch CURRENCY_FORMATION_VERSION", LOG_LEVEL_0);
return;
}
}
//convert from old version
if (ver < 150)
{
LOG_PRINT_MAGENTA("Converting blockchain into a short form...", LOG_LEVEL_0);
WLT_LOG_MAGENTA("Converting blockchain into a short form...", LOG_LEVEL_0);
std::vector<crypto::hash> old_blockchain;
a & old_blockchain;
uint64_t count = 0;
@ -700,7 +700,7 @@ namespace tools
m_chain.push_new_block_id(h, count);
count++;
}
LOG_PRINT_MAGENTA("Converting done", LOG_LEVEL_0);
WLT_LOG_MAGENTA("Converting done", LOG_LEVEL_0);
}
else
{

View file

@ -56,8 +56,7 @@ wallets_manager::wallets_manager():m_pview(&m_view_stub),
m_rpc_proxy(new tools::default_http_core_proxy()),
#endif
m_last_daemon_height(0),
m_last_daemon_is_disconnected(false),
m_last_daemon_height(0),
m_wallet_id_counter(0),
m_ui_opt(AUTO_VAL_INIT(m_ui_opt)),
m_remote_node_mode(false),
@ -68,6 +67,7 @@ wallets_manager::wallets_manager():m_pview(&m_view_stub),
{
#ifndef MOBILE_WALLET_BUILD
m_offers_service.set_disabled(true);
m_pproxy_diganostic_info = m_rpc_proxy->get_proxy_diagnostic_info();
#endif
//m_ccore.get_blockchain_storage().get_attachment_services_manager().add_service(&m_offers_service);
}
@ -272,10 +272,10 @@ bool wallets_manager::init(view::i_view* pview_handler)
{
m_remote_node_mode = true;
auto proxy_ptr = new tools::default_http_core_proxy();
proxy_ptr->set_plast_daemon_is_disconnected(&m_last_daemon_is_disconnected);
proxy_ptr->set_connectivity(HTTP_PROXY_TIMEOUT, HTTP_PROXY_ATTEMPTS_COUNT);
m_rpc_proxy.reset(proxy_ptr);
m_rpc_proxy->set_connection_addr(command_line::get_arg(m_vm, arg_remote_node));
m_pproxy_diganostic_info = m_rpc_proxy->get_proxy_diagnostic_info();
}
if(!command_line::has_arg(m_vm, arg_disable_logs_init))
@ -706,7 +706,8 @@ void wallets_manager::init_wallet_entry(wallet_vs_options& wo, uint64_t id)
wo.stop_for_refresh = false;
wo.plast_daemon_height = &m_last_daemon_height;
wo.plast_daemon_network_state = &m_last_daemon_network_state;
wo.plast_daemon_is_disconnected = &m_last_daemon_is_disconnected;
//wo.plast_daemon_is_disconnected = &(m_rpc_proxy->get_proxy_diagnostic_info().last_daemon_is_disconnected;
wo.m_pproxy_diagnostig_info = m_rpc_proxy->get_proxy_diagnostic_info();
wo.pview = m_pview;
wo.has_related_alias_in_unconfirmed = false;
wo.rpc_wrapper.reset(new tools::wallet_rpc_server(*wo.w.unlocked_get().get()));
@ -852,6 +853,13 @@ std::string wallets_manager::open_wallet(const std::wstring& path, const std::st
w->load(path, password);
if (w->is_watch_only() && !w->is_auditable())
return API_RETURN_CODE_WALLET_WATCH_ONLY_NOT_SUPPORTED;
#ifndef MOBILE_WALLET_BUILD
//disable auditable wallets for now in mobile wallet
if (w->is_auditable())
{
return API_RETURN_CODE_WALLET_AUDITABLE_NOT_SUPPORTED;
}
#endif
w->get_recent_transfers_history(owr.recent_history.history, 0, txs_to_return, owr.recent_history.total_history_items);
//w->get_unconfirmed_transfers(owr.recent_history.unconfirmed);
w->get_unconfirmed_transfers(owr.recent_history.history);
@ -1055,6 +1063,13 @@ std::string wallets_manager::restore_wallet(const std::wstring& path, const std:
{
bool auditable_watch_only = restore_key.find(':') != std::string::npos;
w->restore(path, password, restore_key, auditable_watch_only);
#ifndef MOBILE_WALLET_BUILD
//disable auditable wallets for now in mobile wallet
if (w->is_auditable())
{
return API_RETURN_CODE_WALLET_AUDITABLE_NOT_SUPPORTED;
}
#endif
owr.seed = w->get_account().get_seed_phrase();
}
catch (const tools::error::file_exists&)
@ -1361,7 +1376,9 @@ bool wallets_manager::get_is_remote_daemon_connected()
{
if (!m_remote_node_mode)
return true;
if (m_last_daemon_is_disconnected)
if (m_pproxy_diganostic_info->last_daemon_is_disconnected)
return false;
if (m_pproxy_diganostic_info->is_busy)
return false;
if (time(nullptr) - m_rpc_proxy->get_last_success_interract_time() > DAEMON_IDLE_UPDATE_TIME_MS * 2)
return false;
@ -1372,7 +1389,8 @@ std::string wallets_manager::get_connectivity_status()
{
view::general_connectivity_info gci = AUTO_VAL_INIT(gci);
gci.is_online = get_is_remote_daemon_connected();
gci.last_daemon_is_disconnected = m_last_daemon_is_disconnected;
gci.last_daemon_is_disconnected = m_pproxy_diganostic_info->last_daemon_is_disconnected;
gci.is_server_busy = m_pproxy_diganostic_info->is_busy;
gci.last_proxy_communicate_timestamp = m_rpc_proxy->get_last_success_interract_time();
return epee::serialization::store_t_to_json(gci);
}
@ -1798,7 +1816,7 @@ void wallets_manager::wallet_vs_options::worker_func()
try
{
wsi.wallet_state = view::wallet_status_info::wallet_state_ready;
if (plast_daemon_is_disconnected && plast_daemon_is_disconnected->load())
if (m_pproxy_diagnostig_info->last_daemon_is_disconnected.load())
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
continue;

View file

@ -69,7 +69,8 @@ public:
std::atomic<uint64_t> last_wallet_synch_height;
std::atomic<uint64_t>* plast_daemon_height;
std::atomic<uint64_t>* plast_daemon_network_state;
std::atomic<bool>* plast_daemon_is_disconnected;
//std::atomic<bool>* plast_daemon_is_disconnected;
std::shared_ptr<const tools::proxy_diagnostic_info> m_pproxy_diagnostig_info;
std::atomic<bool> has_related_alias_in_unconfirmed;
std::atomic<bool> need_to_update_wallet_info;
std::atomic<bool> long_refresh_in_progress;
@ -192,7 +193,8 @@ private:
bool m_use_deffered_global_outputs;
std::atomic<uint64_t> m_last_daemon_height;
std::atomic<uint64_t> m_last_daemon_network_state;
std::atomic<bool> m_last_daemon_is_disconnected;
std::shared_ptr<const tools::proxy_diagnostic_info> m_pproxy_diganostic_info;
//std::atomic<bool> m_last_daemon_is_disconnected;
// std::atomic<uint64_t> m_last_wallet_synch_height;
std::atomic<uint64_t> m_wallet_id_counter;
std::atomic<bool> m_dont_save_wallet_at_stop;

View file

@ -8,6 +8,7 @@
#include "currency_core/miner.h"
#include "wallet/wallet2.h"
#include "test_core_time.h"
#include "chaingen.h"
// chaingen-independent helpers that may be used outside of core_tests (for ex. in functional_tests)

View file

@ -26,7 +26,7 @@ std::atomic<int64_t> test_core_time::m_time_shift;
#include "../core_tests/chaingen_helpers.h"
#include "../core_tests/core_state_helper.h"
#define TESTS_DEFAULT_FEE TX_DEFAULT_FEE
//#define TESTS_DEFAULT_FEE TX_DEFAULT_FEE
static std::atomic<uint64_t> s_generated_money_total(0); // TODO: consiger changing to boost::multiprecision::uint128_t
static size_t s_wallets_total_count = 10; // total number of wallet that will be randomly used to generate transactions
@ -40,8 +40,8 @@ typedef std::vector<cct_event_t> cct_events_t;
typedef std::vector<currency::account_base> cct_accounts_t;
typedef std::vector<std::shared_ptr<tools::wallet2>> cct_wallets_t;
static const std::vector<currency::extra_v> empty_extra;
static const std::vector<currency::attachment_v> empty_attachment;
//static const std::vector<currency::extra_v> empty_extra;
//static const std::vector<currency::attachment_v> empty_attachment;
bool create_block_template_manually(const currency::block& prev_block, boost::multiprecision::uint128_t already_generated_coins, const std::vector<const currency::transaction*>& txs, const currency::account_public_address& miner_addr, currency::block& result)
{

View file

@ -32,6 +32,7 @@ void run_plain_wallet_api_test()
{
LOG_PRINT_L0("Creating instance...");
std::string s = plain_wallet::init("195.201.107.230", "11211", boost::dll::program_location().parent_path().string(), 1);
s = plain_wallet::get_export_private_info("E:\\tmp\\check_export");
std::string key = plain_wallet::generate_random_key(10);
std::string test_data = "1234567890 test test ";

View file

@ -518,13 +518,13 @@ TEST(integ_address, payment_id_sizes)
if (pid_size > 0)
crypto::generate_random_bytes(pid_size, &payment_id.front());
currency::account_public_address addr;
currency::account_public_address addr = AUTO_VAL_INIT_T(currency::account_public_address);
addr.spend_public_key = currency::keypair::generate().pub;
addr.view_public_key = currency::keypair::generate().pub;
std::string addr_str = currency::get_account_address_and_payment_id_as_str(addr, payment_id);
currency::account_public_address addr2;
currency::account_public_address addr2 = AUTO_VAL_INIT_T(currency::account_public_address);
std::string integrated_payment_id;
ASSERT_TRUE(currency::get_account_address_and_payment_id_from_str(addr2, integrated_payment_id, addr_str));
@ -538,19 +538,16 @@ TEST(integ_address, payment_id_sizes)
if (pid_size > 0)
crypto::generate_random_bytes(pid_size, &payment_id.front());
currency::account_public_address addr;
currency::account_public_address addr = AUTO_VAL_INIT_T(currency::account_public_address);
addr.spend_public_key = currency::keypair::generate().pub;
addr.view_public_key = currency::keypair::generate().pub;
// the following line is expected to handle oversized payment id well
std::string addr_str = currency::get_account_address_and_payment_id_as_str(addr, payment_id);
currency::account_public_address addr2;
currency::account_public_address addr2 = AUTO_VAL_INIT_T(currency::account_public_address);
std::string integrated_payment_id;
ASSERT_FALSE(currency::get_account_address_and_payment_id_from_str(addr2, integrated_payment_id, addr_str));
ASSERT_NE(addr2, addr);
ASSERT_NE(integrated_payment_id, payment_id);
}

View file

@ -20,13 +20,13 @@
using namespace tools;
namespace lmdb_test
namespace db_test
{
crypto::hash null_hash = AUTO_VAL_INIT(null_hash);
template<typename T>
T random_t_from_range(T from, T to)
inline T random_t_from_range(T from, T to)
{
if (from >= to)
return from;
@ -35,62 +35,82 @@ namespace lmdb_test
return from + result % (to - from + 1);
}
template<typename db_backend_t>
inline std::string get_db_decorated_name()
{
return boost::algorithm::replace_all_copy(boost::algorithm::replace_all_copy(std::string(typeid(db_backend_t).name()), ":", "_"), " ", "_");
}
//////////////////////////////////////////////////////////////////////////////
// basic_test
//////////////////////////////////////////////////////////////////////////////
TEST(lmdb, basic_test)
template<typename db_backend_t>
void basic_test()
{
std::shared_ptr<db::lmdb_db_backend> lmdb_ptr = std::make_shared<db::lmdb_db_backend>();
std::shared_ptr<db_backend_t> backend_ptr = std::make_shared<db_backend_t>();
epee::shared_recursive_mutex db_lock;
db::basic_db_accessor dbb(lmdb_ptr, db_lock);
db::basic_db_accessor dbb(backend_ptr, db_lock);
bool r = false;
r = dbb.open("test_lmdb");
r = dbb.open(get_db_decorated_name<db_backend_t>());
ASSERT_TRUE(r);
db::container_handle tid_decapod;
r = lmdb_ptr->open_container("decapod", tid_decapod);
r = backend_ptr->open_container("decapod", tid_decapod);
ASSERT_TRUE(r);
ASSERT_TRUE(lmdb_ptr->begin_transaction());
ASSERT_TRUE(backend_ptr->begin_transaction());
ASSERT_TRUE(lmdb_ptr->clear(tid_decapod));
ASSERT_TRUE(backend_ptr->clear(tid_decapod));
uint64_t key = 10;
std::string buf = "nxjdu47flrp20soam19e7nfhxbcy48owks03of92sbf31n1oqkanmdb47";
r = lmdb_ptr->set(tid_decapod, (char*)&key, sizeof key, buf.c_str(), buf.size());
r = backend_ptr->set(tid_decapod, (char*)&key, sizeof key, buf.c_str(), buf.size());
ASSERT_TRUE(r);
ASSERT_TRUE(lmdb_ptr->commit_transaction());
ASSERT_TRUE(backend_ptr->commit_transaction());
r = dbb.close();
ASSERT_TRUE(r);
r = dbb.open("test_lmdb");
r = dbb.open(get_db_decorated_name<db_backend_t>());
ASSERT_TRUE(r);
r = lmdb_ptr->open_container("decapod", tid_decapod);
r = backend_ptr->open_container("decapod", tid_decapod);
ASSERT_TRUE(r);
ASSERT_TRUE(lmdb_ptr->begin_transaction());
ASSERT_TRUE(backend_ptr->begin_transaction());
std::string out_buffer;
r = lmdb_ptr->get(tid_decapod, (char*)&key, sizeof key, out_buffer);
r = backend_ptr->get(tid_decapod, (char*)&key, sizeof key, out_buffer);
ASSERT_TRUE(r);
ASSERT_EQ(buf, out_buffer);
ASSERT_TRUE(lmdb_ptr->commit_transaction());
ASSERT_TRUE(backend_ptr->commit_transaction());
r = dbb.close();
ASSERT_TRUE(r);
}
TEST(lmdb, basic_test)
{
basic_test<db::lmdb_db_backend>();
}
TEST(mdbx, basic_test)
{
basic_test<db::mdbx_db_backend>();
}
//////////////////////////////////////////////////////////////////////////////
// multithread_test_1
//////////////////////////////////////////////////////////////////////////////
template<typename db_backend_t>
struct multithread_test_1_t : public db::i_db_callback
{
enum { c_keys_count = 128 };
@ -98,14 +118,14 @@ namespace lmdb_test
size_t m_randomly_mixed_indexes_1[c_keys_count];
size_t m_randomly_mixed_indexes_2[c_keys_count];
epee::shared_recursive_mutex m_db_lock;
std::shared_ptr<db::lmdb_db_backend> m_lmdb_adapter;
std::shared_ptr<db_backend_t> m_backend;
db::basic_db_accessor m_dbb;
db::container_handle m_table_id;
size_t m_counter;
multithread_test_1_t()
: m_lmdb_adapter(std::make_shared<db::lmdb_db_backend>())
, m_dbb(m_lmdb_adapter, m_db_lock)
: m_backend(std::make_shared<db_backend_t>())
, m_dbb(m_backend, m_db_lock)
, m_table_id(0)
, m_counter(0)
{
@ -147,22 +167,22 @@ namespace lmdb_test
i = (i + 1) % c_keys_count;
const crypto::hash& key = m_keys[key_index];
bool r = m_lmdb_adapter->begin_transaction();
bool r = m_backend->begin_transaction();
CHECK_AND_ASSERT_MES_NO_RET(r, "begin_transaction");
// get a value by the given key
std::string value;
if (!m_lmdb_adapter->get(m_table_id, (const char*)&key, sizeof key, value))
if (!m_backend->get(m_table_id, (const char*)&key, sizeof key, value))
{
// if such key does not exist -- add it
char buffer[128];
crypto::generate_random_bytes(sizeof buffer, buffer);
r = m_lmdb_adapter->set(m_table_id, (const char*)&key, sizeof key, buffer, sizeof buffer);
r = m_backend->set(m_table_id, (const char*)&key, sizeof key, buffer, sizeof buffer);
CHECK_AND_ASSERT_MES_NO_RET(r, "set");
size_t table_size = m_lmdb_adapter->size(m_table_id);
size_t table_size = m_backend->size(m_table_id);
r = m_lmdb_adapter->commit_transaction();
r = m_backend->commit_transaction();
CHECK_AND_ASSERT_MES_NO_RET(r, "commit_transaction");
LOG_PRINT_L1("added key index " << key_index << ", table size: " << table_size);
@ -170,7 +190,7 @@ namespace lmdb_test
else
{
// if key exists in the table - do nothing
m_lmdb_adapter->abort_transaction();
m_backend->abort_transaction();
}
epee::misc_utils::sleep_no_w(1);
}
@ -190,20 +210,20 @@ namespace lmdb_test
size_t key_index = m_randomly_mixed_indexes_2[i];
i = (i + 1) % c_keys_count;
const crypto::hash& key = m_keys[key_index];
bool r = m_lmdb_adapter->begin_transaction();
bool r = m_backend->begin_transaction();
CHECK_AND_ASSERT_MES_NO_RET(r, "begin_transaction");
// get a value by the given key
std::string value;
if (m_lmdb_adapter->get(m_table_id, (const char*)&key, sizeof key, value))
if (m_backend->get(m_table_id, (const char*)&key, sizeof key, value))
{
// if key exists in the table -- remove it
r = m_lmdb_adapter->erase(m_table_id, (const char*)&key, sizeof key);
r = m_backend->erase(m_table_id, (const char*)&key, sizeof key);
CHECK_AND_ASSERT_MES_NO_RET(r, "erase");
size_t table_size = m_lmdb_adapter->size(m_table_id);
size_t table_size = m_backend->size(m_table_id);
r = m_lmdb_adapter->commit_transaction();
r = m_backend->commit_transaction();
CHECK_AND_ASSERT_MES_NO_RET(r, "commit_transaction");
LOG_PRINT_L1("erased key index " << key_index << ", table size: " << table_size);
@ -213,7 +233,7 @@ namespace lmdb_test
else
{
// if no such key exists in the table - do nothing
m_lmdb_adapter->abort_transaction();
m_backend->abort_transaction();
}
epee::misc_utils::sleep_no_w(1);
}
@ -234,18 +254,18 @@ namespace lmdb_test
size_t key_index = m_randomly_mixed_indexes_2[i];
i = (i + 1) % c_keys_count;
const crypto::hash& key = m_keys[key_index];
bool r = m_lmdb_adapter->begin_transaction(true); // request Read-Only transaction
bool r = m_backend->begin_transaction(true); // request Read-Only transaction
CHECK_AND_ASSERT_MES_NO_RET(r, "begin_transaction(RO=true)");
// get a value by the given key
std::string value;
if (m_lmdb_adapter->get(m_table_id, (const char*)&key, sizeof key, value))
if (m_backend->get(m_table_id, (const char*)&key, sizeof key, value))
{
sum += *reinterpret_cast<const uint64_t*>(value.data());
size_t table_size = m_lmdb_adapter->size(m_table_id);
size_t table_size = m_backend->size(m_table_id);
r = m_lmdb_adapter->commit_transaction();
r = m_backend->commit_transaction();
CHECK_AND_ASSERT_MES_NO_RET(r, "commit_transaction");
if (table_size == 2)
@ -254,7 +274,7 @@ namespace lmdb_test
else
{
// if no such key exists in the table - do nothing
m_lmdb_adapter->abort_transaction();
m_backend->abort_transaction();
}
epee::misc_utils::sleep_no_w(1);
}
@ -263,16 +283,16 @@ namespace lmdb_test
bool check()
{
size_t table_size = m_lmdb_adapter->size(m_table_id);
size_t table_size = m_backend->size(m_table_id);
CHECK_AND_ASSERT_MES(table_size == 2, false, "2 elements are expected to left");
m_counter = 0;
bool r = m_lmdb_adapter->begin_transaction();
bool r = m_backend->begin_transaction();
CHECK_AND_ASSERT_MES(r, false, "begin_transaction");
m_lmdb_adapter->enumerate(m_table_id, this);
m_backend->enumerate(m_table_id, this);
r = m_lmdb_adapter->commit_transaction();
r = m_backend->commit_transaction();
CHECK_AND_ASSERT_MES(r, false, "commit_transaction");
return m_counter == 2;
@ -308,13 +328,13 @@ namespace lmdb_test
{
bool r = m_dbb.open("multithread_test_1_t");
CHECK_AND_ASSERT_MES(r, false, "m_dbb.open");
r = m_lmdb_adapter->open_container("table1_", m_table_id);
r = m_backend->open_container("table1_", m_table_id);
CHECK_AND_ASSERT_MES(r, false, "open_table");
r = m_lmdb_adapter->begin_transaction();
r = m_backend->begin_transaction();
CHECK_AND_ASSERT_MES(r, false, "begin_transaction");
r = m_lmdb_adapter->clear(m_table_id);
r = m_backend->clear(m_table_id);
CHECK_AND_ASSERT_MES(r, false, "clear_table");
r = m_lmdb_adapter->commit_transaction();
r = m_backend->commit_transaction();
CHECK_AND_ASSERT_MES(r, false, "commit_transaction");
std::atomic<bool> stop_adder(false), stop_deleter(false);
@ -336,9 +356,10 @@ namespace lmdb_test
m_dbb.close();
return r;
}
};
}; // multithread_test_1_t
TEST(lmdb, multithread_test_1)
template<typename db_backend_t>
void multithread_test_1()
{
char prng_state[200] = {};
crypto::random_prng_get_state(prng_state, sizeof prng_state); // store current RPNG state
@ -347,7 +368,7 @@ namespace lmdb_test
bool result = false;
try
{
multithread_test_1_t t;
multithread_test_1_t<db_backend_t> t;
result = t.run();
}
catch (std::exception& e)
@ -361,8 +382,19 @@ namespace lmdb_test
ASSERT_TRUE(result);
}
TEST(lmdb, multithread_test_1)
{
multithread_test_1<db::lmdb_db_backend>();
}
TEST(mdbx, multithread_test_1)
{
multithread_test_1<db::mdbx_db_backend>();
}
//////////////////////////////////////////////////////////////////////////////
// bridge_basic_test
// basic_accessor_test
//////////////////////////////////////////////////////////////////////////////
struct simple_serializable_t
{
@ -393,11 +425,12 @@ namespace lmdb_test
return std::memcmp(&_v1, &_v2, sizeof _v1) == 0;
}
TEST(lmdb, bridge_basic_test)
template<typename db_backend_t>
void basic_accessor_test()
{
std::shared_ptr<db::lmdb_db_backend> lmdb_ptr = std::make_shared<db::lmdb_db_backend>();
std::shared_ptr<db_backend_t> backend_ptr = std::make_shared<db_backend_t>();
epee::shared_recursive_mutex db_lock;
db::basic_db_accessor dbb(lmdb_ptr, db_lock);
db::basic_db_accessor dbb(backend_ptr, db_lock);
bool r = false;
@ -405,7 +438,7 @@ namespace lmdb_test
ASSERT_TRUE(r);
db::container_handle tid_decapod;
r = lmdb_ptr->open_container("decapod", tid_decapod);
r = backend_ptr->open_container("decapod", tid_decapod);
ASSERT_TRUE(r);
ASSERT_TRUE(dbb.begin_transaction());
@ -474,6 +507,16 @@ namespace lmdb_test
ASSERT_TRUE(r);
}
TEST(lmdb, basic_accessor_test)
{
basic_accessor_test<db::lmdb_db_backend>();
}
TEST(mdbx, basic_accessor_test)
{
basic_accessor_test<db::mdbx_db_backend>();
}
//////////////////////////////////////////////////////////////////////////////
// single_value_test
//////////////////////////////////////////////////////////////////////////////
@ -489,13 +532,14 @@ namespace lmdb_test
END_SERIALIZE()
};
TEST(lmdb, single_value_test)
template<typename db_backend_t>
void single_value_test()
{
const std::string options_table_name("options");
std::shared_ptr<db::lmdb_db_backend> lmdb_ptr = std::make_shared<db::lmdb_db_backend>();
std::shared_ptr<db_backend_t> backend_ptr = std::make_shared<db_backend_t>();
epee::shared_recursive_mutex db_lock;
db::basic_db_accessor dbb(lmdb_ptr, db_lock);
db::basic_db_accessor dbb(backend_ptr, db_lock);
db::basic_key_value_accessor<uint64_t, uint64_t /* does not matter */, false /* does not matter */ > options_container(dbb);
db::solo_db_value<uint64_t, uint64_t, decltype(options_container), false> option_uint64(0, options_container);
@ -506,7 +550,7 @@ namespace lmdb_test
// clear table
db::container_handle options_tid;
ASSERT_TRUE(lmdb_ptr->open_container(options_table_name, options_tid));
ASSERT_TRUE(backend_ptr->open_container(options_table_name, options_tid));
ASSERT_TRUE(dbb.begin_transaction());
ASSERT_TRUE(dbb.clear(options_tid));
dbb.commit_transaction();
@ -560,19 +604,29 @@ namespace lmdb_test
ASSERT_TRUE(dbb.close());
}
TEST(lmdb, single_value_test)
{
single_value_test<db::lmdb_db_backend>();
}
TEST(mdbx, single_value_test)
{
single_value_test<db::mdbx_db_backend>();
}
//////////////////////////////////////////////////////////////////////////////
// array_basic_test
//////////////////////////////////////////////////////////////////////////////
TEST(lmdb, array_basic_test)
template<typename db_backend_t>
void array_basic_test()
{
bool r = false;
const std::string array_table_name("test_array");
std::shared_ptr<db::lmdb_db_backend> lmdb_ptr = std::make_shared<db::lmdb_db_backend>();
std::shared_ptr<db_backend_t> backend_ptr = std::make_shared<db_backend_t>();
epee::shared_recursive_mutex db_lock;
db::basic_db_accessor dbb(lmdb_ptr, db_lock);
db::basic_db_accessor dbb(backend_ptr, db_lock);
db::basic_key_to_array_accessor<uint64_t, serializable_string, true> db_array(dbb);
@ -580,7 +634,7 @@ namespace lmdb_test
// clear table
db::container_handle tid;
ASSERT_TRUE(lmdb_ptr->open_container(array_table_name, tid));
ASSERT_TRUE(backend_ptr->open_container(array_table_name, tid));
ASSERT_TRUE(dbb.begin_transaction());
ASSERT_TRUE(dbb.clear(tid));
dbb.commit_transaction();
@ -681,18 +735,30 @@ namespace lmdb_test
ASSERT_TRUE(dbb.close());
}
TEST(lmdb, array_basic_test)
{
array_basic_test<db::lmdb_db_backend>();
}
TEST(mdbx, array_basic_test)
{
array_basic_test<db::mdbx_db_backend>();
}
//////////////////////////////////////////////////////////////////////////////
// array_accessor_test
//////////////////////////////////////////////////////////////////////////////
TEST(lmdb, array_accessor_test)
template<typename db_backend_t>
void array_accessor_test()
{
bool r = false;
const std::string array_table_name("array");
std::shared_ptr<db::lmdb_db_backend> lmdb_ptr = std::make_shared<db::lmdb_db_backend>();
std::shared_ptr<db_backend_t> backend_ptr = std::make_shared<db_backend_t>();
epee::shared_recursive_mutex db_lock;
db::basic_db_accessor dbb(lmdb_ptr, db_lock);
db::basic_db_accessor dbb(backend_ptr, db_lock);
db::array_accessor<serializable_string, true> db_array(dbb);
@ -700,7 +766,7 @@ namespace lmdb_test
// clear table
db::container_handle tid;
ASSERT_TRUE(lmdb_ptr->open_container(array_table_name, tid));
ASSERT_TRUE(backend_ptr->open_container(array_table_name, tid));
ASSERT_TRUE(dbb.begin_transaction());
ASSERT_TRUE(dbb.clear(tid));
dbb.commit_transaction();
@ -787,18 +853,29 @@ namespace lmdb_test
db_array.commit_transaction();
}
TEST(lmdb, array_accessor_test)
{
array_accessor_test<db::lmdb_db_backend>();
}
TEST(mdbx, array_accessor_test)
{
array_accessor_test<db::mdbx_db_backend>();
}
//////////////////////////////////////////////////////////////////////////////
// key_value_test
//////////////////////////////////////////////////////////////////////////////
TEST(lmdb, key_value_test)
template<typename db_backend_t>
void key_value_test()
{
bool r = false;
const std::string array_table_name("key-value");
std::shared_ptr<db::lmdb_db_backend> lmdb_ptr = std::make_shared<db::lmdb_db_backend>();
std::shared_ptr<db_backend_t> backend_ptr = std::make_shared<db_backend_t>();
epee::shared_recursive_mutex db_lock;
db::basic_db_accessor dbb(lmdb_ptr, db_lock);
db::basic_db_accessor dbb(backend_ptr, db_lock);
db::basic_key_value_accessor<uint64_t, serializable_string, true> db_key_value_map(dbb);
@ -806,7 +883,7 @@ namespace lmdb_test
// clear table
db::container_handle tid;
ASSERT_TRUE(lmdb_ptr->open_container(array_table_name, tid));
ASSERT_TRUE(backend_ptr->open_container(array_table_name, tid));
ASSERT_TRUE(dbb.begin_transaction());
ASSERT_TRUE(dbb.clear(tid));
dbb.commit_transaction();
@ -889,6 +966,16 @@ namespace lmdb_test
db_key_value_map.commit_transaction();
}
TEST(lmdb, key_value_test)
{
key_value_test<db::lmdb_db_backend>();
}
TEST(mdbx, key_value_test)
{
key_value_test<db::mdbx_db_backend>();
}
//////////////////////////////////////////////////////////////////////////////
// 2gb_test
@ -903,10 +990,10 @@ namespace lmdb_test
static const uint64_t buffer_size = 64 * 1024; // 64 KB
static const uint64_t db_total_size = static_cast<uint64_t>(2.1 * 1024 * 1024 * 1024); // 2.1 GB -- a bit more than 2GB to test 2GB boundary
static const std::string db_file_path = boost::algorithm::replace_all_copy(boost::algorithm::replace_all_copy(std::string("2gb_") + typeid(db_backend_t).name() + "_test", ":", "_"), " ", "_");
static const std::string db_file_path = std::string("2gb_") + get_db_decorated_name<db_backend_t>() + "_test";
std::shared_ptr<db_backend_t> lmdb_ptr = std::make_shared<db_backend_t>();
db::basic_db_accessor bdba(lmdb_ptr, rw_lock);
std::shared_ptr<db_backend_t> backend_ptr = std::make_shared<db_backend_t>();
db::basic_db_accessor bdba(backend_ptr, rw_lock);
//
// write data
@ -916,11 +1003,11 @@ namespace lmdb_test
ASSERT_TRUE(r);
db::container_handle h;
r = lmdb_ptr->open_container("c1", h);
r = backend_ptr->open_container("c1", h);
ASSERT_TRUE(r);
ASSERT_TRUE(lmdb_ptr->begin_transaction());
ASSERT_TRUE(lmdb_ptr->clear(h));
ASSERT_TRUE(backend_ptr->begin_transaction());
ASSERT_TRUE(backend_ptr->clear(h));
std::vector<uint8_t> buffer;
buffer.resize(buffer_size);
@ -950,20 +1037,20 @@ namespace lmdb_test
uint64_t total_data = 0;
for (uint64_t key = 0; key < db_total_size / buffer_size; ++key)
{
r = lmdb_ptr->set(h, (char*)&key, sizeof key, reinterpret_cast<const char*>(buffer.data()), buffer_size);
r = backend_ptr->set(h, (char*)&key, sizeof key, reinterpret_cast<const char*>(buffer.data()), buffer_size);
ASSERT_TRUE(r);
total_data += buffer_size;
if (key % 1024 == 0)
{
ASSERT_TRUE(lmdb_ptr->commit_transaction());
//ASSERT_TRUE(lmdb_ptr->resize_if_needed());
ASSERT_TRUE(lmdb_ptr->begin_transaction());
ASSERT_TRUE(backend_ptr->commit_transaction());
//ASSERT_TRUE(backend_ptr->resize_if_needed());
ASSERT_TRUE(backend_ptr->begin_transaction());
std::cout << total_data / 1024 / 1024 << " MB written to DB" << ENDL;
}
}
ASSERT_TRUE(lmdb_ptr->commit_transaction());
ASSERT_TRUE(backend_ptr->commit_transaction());
r = bdba.close();
ASSERT_TRUE(r);
@ -975,16 +1062,16 @@ namespace lmdb_test
r = bdba.open(db_file_path);
ASSERT_TRUE(r);
r = lmdb_ptr->open_container("c1", h);
r = backend_ptr->open_container("c1", h);
ASSERT_TRUE(r);
ASSERT_TRUE(lmdb_ptr->begin_transaction());
ASSERT_TRUE(backend_ptr->begin_transaction());
std::string out_buffer;
total_data = 0;
for (uint64_t key = 0; key < db_total_size / buffer_size; ++key)
{
r = lmdb_ptr->get(h, (char*)&key, sizeof key, out_buffer);
r = backend_ptr->get(h, (char*)&key, sizeof key, out_buffer);
ASSERT_TRUE(r);
ASSERT_EQ(buffer_size, out_buffer.size());
@ -1046,7 +1133,7 @@ namespace lmdb_test
std::cout << total_data / 1024 / 1024 << " MB read from DB" << ENDL;
}
ASSERT_TRUE(lmdb_ptr->commit_transaction());
ASSERT_TRUE(backend_ptr->commit_transaction());
r = bdba.close();
ASSERT_TRUE(r);
@ -1065,4 +1152,99 @@ namespace lmdb_test
db_2gb_test<db::mdbx_db_backend>();
}
//////////////////////////////////////////////////////////////////////////////
// close_contaier_test
//////////////////////////////////////////////////////////////////////////////
template<typename db_backend_t>
void close_contaier_test()
{
std::shared_ptr<db_backend_t> backend_ptr = std::make_shared<db_backend_t>();
epee::shared_recursive_mutex db_lock;
db::basic_db_accessor dbb(backend_ptr, db_lock);
bool r = false;
r = dbb.open(get_db_decorated_name<db_backend_t>());
ASSERT_TRUE(r);
std::unordered_map<uint64_t, crypto::hash> map;
std::vector<size_t> container_ids;
static const size_t containers_total = 1000; // this number considered to be much higher than max opened containers limits
for (size_t i = 0; i < containers_total; ++i)
{
crypto::hash h;
crypto::generate_random_bytes(sizeof h, &h);
map.insert(std::make_pair(i, h));
container_ids.push_back(i);
}
std::shuffle(container_ids.begin(), container_ids.end(), crypto::uniform_random_bit_generator());
for (size_t i = 0; i < containers_total; ++i)
{
size_t container_id = container_ids[i];
db::container_handle cid;
r = backend_ptr->open_container("container_#" + epee::string_tools::num_to_string_fast(container_id), cid);
ASSERT_TRUE(r);
ASSERT_TRUE(backend_ptr->begin_transaction());
ASSERT_TRUE(backend_ptr->clear(cid));
const crypto::hash& h = map[container_id];
r = backend_ptr->set(cid, (char*)&container_id, sizeof container_id, (char*)&h, sizeof h);
ASSERT_TRUE(r);
ASSERT_TRUE(backend_ptr->commit_transaction());
r = backend_ptr->close_container(cid);
ASSERT_TRUE(r);
}
std::shuffle(container_ids.begin(), container_ids.end(), crypto::uniform_random_bit_generator());
for (size_t i = 0; i < containers_total; ++i)
{
size_t container_id = container_ids[i];
db::container_handle cid;
r = backend_ptr->open_container("container_#" + epee::string_tools::num_to_string_fast(container_id), cid);
ASSERT_TRUE(r);
ASSERT_TRUE(backend_ptr->begin_transaction());
std::string out_buffer;
r = backend_ptr->get(cid, (char*)&container_id, sizeof container_id, out_buffer);
ASSERT_TRUE(r);
const crypto::hash& h_buff = *reinterpret_cast<const crypto::hash*>(out_buffer.c_str());
const crypto::hash& h = map[container_id];
ASSERT_EQ(h, h_buff);
ASSERT_TRUE(backend_ptr->commit_transaction());
r = backend_ptr->close_container(cid);
ASSERT_TRUE(r);
}
r = dbb.close();
ASSERT_TRUE(r);
}
TEST(lmdb, close_contaier_test)
{
close_contaier_test<db::lmdb_db_backend>();
}
TEST(mdbx, close_contaier_test)
{
close_contaier_test<db::mdbx_db_backend>();
}
} // namespace lmdb_test