1
0
Fork 0
forked from lthn/blockchain

plain_wallet api refactored due to ios app crash

This commit is contained in:
cryptozoidberg 2020-05-13 22:01:40 +02:00
parent b97065beba
commit 9e983b70b2
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
2 changed files with 108 additions and 34 deletions

View file

@ -34,5 +34,6 @@
#define API_RETURN_CODE_WRONG_SEED "WRONG_SEED"
#define API_RETURN_CODE_GENESIS_MISMATCH "GENESIS_MISMATCH"
#define API_RETURN_CODE_DISCONNECTED "DISCONNECTED"
#define API_RETURN_CODE_UNINITIALIZED "UNINITIALIZED"

View file

@ -27,21 +27,42 @@
#define GENERAL_INTERNAL_ERRROR_INIT "Failed to intialize library"
//TODO: global objects, subject to refactoring
wallets_manager gwm;
std::atomic<bool> initialized(false);
std::atomic<uint64_t> gjobs_counter(1);
std::map<uint64_t, std::string> gjobs;
epee::critical_section gjobs_lock;
std::string gconfig_folder;
struct plain_wallet_instance
{
plain_wallet_instance() :initialized(false), gjobs_counter(1)
{}
wallets_manager gwm;
std::atomic<bool> initialized;
std::atomic<uint64_t> gjobs_counter;
std::map<uint64_t, std::string> gjobs;
epee::critical_section gjobs_lock;
};
std::shared_ptr<plain_wallet_instance> ginstance_ptr;
epee::misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler([&]()
{
std::cout << "[LEAVE HANDLER CALLED]" << ENDL;
});
namespace plain_wallet
{
typedef epee::json_rpc::response<epee::json_rpc::dummy_result, error> error_response;
std::string get_set_working_dir(bool need_to_set = false, const std::string val = "")
{
static std::string working_dir;
if (need_to_set)
working_dir = val;
return working_dir;
}
std::string get_bundle_working_dir()
{
return gconfig_folder;
return get_set_working_dir();
// #ifdef WIN32
// return boost::dll::program_location().parent_path().string();
// #elif IOS_BUILD
@ -56,7 +77,7 @@ namespace plain_wallet
}
void set_bundle_working_dir(const std::string& dir)
{
gconfig_folder = dir;
get_set_working_dir(true, dir);
}
std::string get_wallets_folder()
@ -102,15 +123,33 @@ namespace plain_wallet
return "{}";
}
void deinit()
{
auto local_ptr = std::atomic_load(&ginstance_ptr);
if (local_ptr)
{
std::atomic_store(&ginstance_ptr, std::shared_ptr<plain_wallet_instance>());
//wait other callers finish
local_ptr->gjobs_lock.lock();
local_ptr->gjobs_lock.unlock();
local_ptr.reset();
}
}
std::string init(const std::string& ip, const std::string& port, const std::string& working_dir, int log_level)
{
if (initialized)
auto local_ptr = std::atomic_load(&ginstance_ptr);
if (local_ptr)
{
LOG_ERROR("Double-initialization in plain_wallet detected.");
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_ALREADY_EXISTS;
return epee::serialization::store_t_to_json(ok_response);
}
std::cout << "[INIT PLAIN_WALLET_INSTANCE]" << ENDL;
std::shared_ptr<plain_wallet_instance> ptr(new plain_wallet_instance());
set_bundle_working_dir(working_dir);
initialize_logs(log_level);
@ -122,13 +161,13 @@ namespace plain_wallet
args[1] = const_cast<char*>(argss_1.c_str());
args[2] = const_cast<char*>(argss_2.c_str());
args[3] = nullptr;
if (!gwm.init(3, args, nullptr))
if (!ptr->gwm.init(3, args, nullptr))
{
LOG_ERROR("Failed to init wallets_manager");
return GENERAL_INTERNAL_ERRROR_INIT;
}
if(!gwm.start())
if(!ptr->gwm.start())
{
LOG_ERROR("Failed to start wallets_manager");
return GENERAL_INTERNAL_ERRROR_INIT;
@ -155,7 +194,7 @@ namespace plain_wallet
return epee::serialization::store_t_to_json(err_result);
}
initialized = true;
std::atomic_store(&ginstance_ptr, ptr);
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);
@ -213,9 +252,21 @@ namespace plain_wallet
return epee::serialization::store_t_to_json(ok_response);
}
#define GET_INSTANCE_PTR(ptr_name) \
auto ptr_name = std::atomic_load(&ginstance_ptr); \
if (!ptr_name) \
{ \
LOG_ERROR("Core already deinitialised or not initialized yet."); \
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_UNINITIALIZED; \
return epee::serialization::store_t_to_json(ok_response); \
}
std::string get_connectivity_status()
{
return gwm.get_connectivity_status();
GET_INSTANCE_PTR(inst_ptr);
return inst_ptr->gwm.get_connectivity_status();
}
std::string get_version()
@ -254,16 +305,18 @@ namespace plain_wallet
std::string open(const std::string& path, const std::string& password)
{
GET_INSTANCE_PTR(inst_ptr);
std::string full_path = get_wallets_folder() + path;
epee::json_rpc::response<view::open_wallet_response, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
std::string rsp = gwm.open_wallet(epee::string_encoding::convert_to_unicode(full_path), password, 20, ok_response.result);
std::string rsp = inst_ptr->gwm.open_wallet(epee::string_encoding::convert_to_unicode(full_path), password, 20, ok_response.result);
if (rsp == API_RETURN_CODE_OK || rsp == API_RETURN_CODE_FILE_RESTORED)
{
if (rsp == API_RETURN_CODE_FILE_RESTORED)
{
ok_response.result.recovered = true;
}
gwm.run_wallet(ok_response.result.wallet_id);
inst_ptr->gwm.run_wallet(ok_response.result.wallet_id);
return epee::serialization::store_t_to_json(ok_response);
}
@ -271,18 +324,21 @@ namespace plain_wallet
err_result.error.code = rsp;
return epee::serialization::store_t_to_json(err_result);
}
std::string restore(const std::string& seed, const std::string& path, const std::string& password)
{
GET_INSTANCE_PTR(inst_ptr);
std::string full_path = get_wallets_folder() + path;
epee::json_rpc::response<view::open_wallet_response, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
std::string rsp = gwm.restore_wallet(epee::string_encoding::convert_to_unicode(full_path), password, seed, ok_response.result);
std::string rsp = inst_ptr->gwm.restore_wallet(epee::string_encoding::convert_to_unicode(full_path), password, seed, ok_response.result);
if (rsp == API_RETURN_CODE_OK || rsp == API_RETURN_CODE_FILE_RESTORED)
{
if (rsp == API_RETURN_CODE_FILE_RESTORED)
{
ok_response.result.recovered = true;
}
gwm.run_wallet(ok_response.result.wallet_id);
inst_ptr->gwm.run_wallet(ok_response.result.wallet_id);
return epee::serialization::store_t_to_json(ok_response);
}
error_response err_result = AUTO_VAL_INIT(err_result);
@ -292,16 +348,18 @@ namespace plain_wallet
std::string generate(const std::string& path, const std::string& password)
{
GET_INSTANCE_PTR(inst_ptr);
std::string full_path = get_wallets_folder() + path;
epee::json_rpc::response<view::open_wallet_response, epee::json_rpc::dummy_error> ok_response = AUTO_VAL_INIT(ok_response);
std::string rsp = gwm.generate_wallet(epee::string_encoding::convert_to_unicode(full_path), password, ok_response.result);
std::string rsp = inst_ptr->gwm.generate_wallet(epee::string_encoding::convert_to_unicode(full_path), password, ok_response.result);
if (rsp == API_RETURN_CODE_OK || rsp == API_RETURN_CODE_FILE_RESTORED)
{
if (rsp == API_RETURN_CODE_FILE_RESTORED)
{
ok_response.result.recovered = true;
}
gwm.run_wallet(ok_response.result.wallet_id);
inst_ptr->gwm.run_wallet(ok_response.result.wallet_id);
return epee::serialization::store_t_to_json(ok_response);
}
error_response err_result = AUTO_VAL_INIT(err_result);
@ -311,34 +369,44 @@ namespace plain_wallet
std::string close_wallet(hwallet h)
{
GET_INSTANCE_PTR(inst_ptr);
std::string r = "{\"response\": \"";
r += gwm.close_wallet(h);
r += inst_ptr->gwm.close_wallet(h);
r += "\"}";
return r;
}
std::string get_wallet_status(hwallet h)
{
return gwm.get_wallet_status(h);
GET_INSTANCE_PTR(inst_ptr);
return inst_ptr->gwm.get_wallet_status(h);
}
std::string invoke(hwallet h, const std::string& params)
{
return gwm.invoke(h, params);
GET_INSTANCE_PTR(inst_ptr);
return inst_ptr->gwm.invoke(h, params);
}
void put_result(uint64_t job_id, const std::string& res)
{
CRITICAL_REGION_LOCAL(gjobs_lock);
gjobs[job_id] = res;
auto inst_ptr = std::atomic_load(&ginstance_ptr);
if (!inst_ptr)
{
return;
}
CRITICAL_REGION_LOCAL(inst_ptr->gjobs_lock);
inst_ptr->gjobs[job_id] = res;
LOG_PRINT_L2("[ASYNC_CALL]: Finished(result put), job id: " << job_id);
}
std::string async_call(const std::string& method_name, uint64_t instance_id, const std::string& params)
{
GET_INSTANCE_PTR(inst_ptr);
std::function<void()> async_callback;
uint64_t job_id = gjobs_counter++;
uint64_t job_id = inst_ptr->gjobs_counter++;
if (method_name == "close")
{
async_callback = [job_id, instance_id]()
@ -413,17 +481,22 @@ namespace plain_wallet
std::string try_pull_result(uint64_t job_id)
{
//TODO: need refactoring
CRITICAL_REGION_LOCAL(gjobs_lock);
auto it = gjobs.find(job_id);
if (it == gjobs.end())
{
return "{\"delivered\": false}";
auto inst_ptr = std::atomic_load(&ginstance_ptr);
if (!inst_ptr)
{
return "{\"status\": \"canceled\"}";
}
std::string res = "{\"delivered\": true, \"result\": ";
//TODO: need refactoring
CRITICAL_REGION_LOCAL(inst_ptr->gjobs_lock);
auto it = inst_ptr->gjobs.find(job_id);
if (it == inst_ptr->gjobs.end())
{
return "{\"status\": \"idle\"}";
}
std::string res = "{\"status\": \"delivered\", \"result\": ";
res += it->second;
res += " }";
gjobs.erase(it);
inst_ptr->gjobs.erase(it);
return res;
}