Commit 29d98fbc authored by Ashot's avatar Ashot
Browse files

Added functionality to update wallet from command line

parent 963370aa
Showing with 238 additions and 19 deletions
+238 -19
......@@ -209,6 +209,7 @@ libbitcoin_server_a_SOURCES = \
rpcmining.cpp \
rpcmisc.cpp \
rpcnet.cpp \
rpcupdate.cpp \
rpcrawtransaction.cpp \
rpcserver.cpp \
script/sigcache.cpp \
......
......@@ -1303,7 +1303,7 @@ void BitcoinGUI::handleRestart(QStringList args)
void BitcoinGUI::checkUpdate()
{
if (updater.GetStatus())
if (updater.Check())
{
UpdateDialog::GetInstance()->setCurrentVersion(QString::fromStdString(FormatVersion(CLIENT_VERSION)));
UpdateDialog::GetInstance()->setUpdateVersion(QString::fromStdString(FormatVersion(updater.GetVersion())));
......
......@@ -98,7 +98,7 @@ void UpdateDialog::selectionChanged(int index)
}
};
void UpdateProgressBar(int now, int total)
void UpdateProgressBar(curl_off_t now, curl_off_t total)
{
QCoreApplication::processEvents();
if (now != 0 && total != 0)
......
......@@ -370,6 +370,7 @@ static const CRPCCommand vRPCCommands[] =
{ "wallet", "walletlock", &walletlock, true, false, true },
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, true, false, true },
{ "wallet", "walletpassphrase", &walletpassphrase, true, false, true },
{ "wallet", "update", &update, true, false, true },
#endif // ENABLE_WALLET
};
......
......@@ -242,6 +242,7 @@ extern json_spirit::Value mnsync(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value snsync(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value service(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value node(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value update(const json_spirit::Array& params, bool fHelp);
// in rest.cpp
extern bool HTTPReq_REST(AcceptedConnection *conn,
......
// Copyright (c) 2014-2018 The Crown developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "main.h"
#include "db.h"
#include "init.h"
#include "systemnodeconfig.h"
#include "systemnode.h"
#include "systemnodeman.h"
#include "activesystemnode.h"
#include "rpcserver.h"
#include "utilmoneystr.h"
#include "wallet.h"
#include "key.h"
#include "base58.h"
#include "updater.h"
#include "json/json_spirit_utils.h"
#include "json/json_spirit_value.h"
#include <boost/thread.hpp>
using namespace json_spirit;
using namespace std;
namespace RPCUpdate
{
Object statusObj;
bool Started = false;
void progressFunction(curl_off_t now, curl_off_t total)
{
int percent = 0;
if (total != 0) {
percent = now * 100 / total;
}
if (statusObj.size() == 0) {
statusObj.push_back(Pair("Download", "In Progress"));
}
if ((now == total) && now != 0) {
Started = false;
statusObj[0] = Pair("Download", "Done");
} else if (now != total) {
Started = true;
statusObj[0] = Pair("Download", strprintf("%0.1f/%0.1fMB, %d%%",
double(now) / 1024 / 1024,
double(total) / 1024 / 1024,
percent));
}
}
}
void RPCDownload()
{
RPCUpdate::statusObj.clear();
// Create temporary directory
boost::filesystem::path dir = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
bool result = TryCreateDirectory(dir);
if (!result) {
throw runtime_error("Failed to create directory" + dir.string());
}
// Download archive
std::string url = updater.GetDownloadUrl();
std::string archivePath = (dir / boost::filesystem::path(url).filename()).string();
updater.DownloadFile(url, archivePath, &RPCUpdate::progressFunction);
RPCUpdate::statusObj[0] = Pair("Download", "Done - " + archivePath);
}
void RPCInstall()
{
RPCUpdate::statusObj.clear();
// Create temporary directory
boost::filesystem::path dir = GetTempPath() / boost::filesystem::unique_path();
bool result = TryCreateDirectory(dir);
if (!result) {
throw runtime_error("Failed to create directory" + dir.string());
}
// Download archive
std::string url = updater.GetDownloadUrl();
std::string archivePath = (dir / boost::filesystem::path(url).filename()).string();
updater.DownloadFile(url, archivePath, &RPCUpdate::progressFunction);
// Extract archive
result = TryCreateDirectory(dir / "archive");
if (!result) {
throw runtime_error("Failed to create directory" + (dir / "archive").string());
}
std::string strCommand = "unzip -q " + archivePath + " -d " + (dir / "archive").string();
int nErr = ::system(strCommand.c_str());
if (nErr) {
LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr);
RPCUpdate::statusObj.push_back(Pair("Extract", "Error. Check debug.log"));
} else {
RPCUpdate::statusObj.push_back(Pair("Extract", "Done"));
}
// Copy files to /usr/
if (!nErr) {
strCommand = "cp -r " + (dir / "archive/*/*").string() + " /usr/";
nErr = ::system(strCommand.c_str());
if (nErr) {
LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr);
RPCUpdate::statusObj.push_back(Pair("Install", "Error. Check debug.log."));
} else {
RPCUpdate::statusObj.push_back(Pair("Install", "Done"));
}
}
boost::filesystem::remove_all(dir);
}
Value update(const Array& params, bool fHelp)
{
string strCommand;
if (params.size() >= 1)
strCommand = params[0].get_str();
if (fHelp || (strCommand != "check" && strCommand != "download" && strCommand != "status" && strCommand != "install"))
throw runtime_error(
"update \"command\"... ( \"passphrase\" )\n"
"Set of commands to check and download application updates\n"
"\nArguments:\n"
"1. \"command\" (string or set of strings, required) The command to execute\n"
"2. \"passphrase\" (string, optional) The wallet passphrase\n"
"\nAvailable commands:\n"
" check - Check for application updates\n"
" download - Download a new version\n"
" status - Check download status\n"
" install - Install update\n"
);
if (strCommand == "check")
{
if (params.size() > 1) {
throw runtime_error("Too many parameters\n");
}
if (updater.Check())
{
// There is an update
Object obj;
obj.push_back(Pair("Current Version", FormatVersion(CLIENT_VERSION)));
obj.push_back(Pair("Update Version", FormatVersion(updater.GetVersion())));
obj.push_back(Pair("OS", updater.GetOsString()));
obj.push_back(Pair("Url", updater.GetDownloadUrl()));
obj.push_back(Pair("Sha256hash", updater.GetDownloadSha256Sum()));
return obj;
}
return "You are running the latest version of Crown - " + FormatVersion(CLIENT_VERSION);
}
if (strCommand == "download")
{
if (!updater.Check())
{
return "You are running the latest version of Crown - " + FormatVersion(CLIENT_VERSION);
}
if (RPCUpdate::Started)
{
return "Download is in progress. Run 'crown-cli update status' to check the status.";
}
boost::thread t(boost::bind(&RPCDownload));
return "Crown download started. \nRun 'crown-cli update status' to check download status.";
}
if (strCommand == "status")
{
return RPCUpdate::statusObj;
}
if (strCommand == "install")
{
if (!updater.Check())
{
return "You are running the latest version of Crown - " + FormatVersion(CLIENT_VERSION);
}
if (RPCUpdate::Started)
{
return "Download is in progress. Run 'crown-cli update status' to check the status.";
}
boost::thread t(boost::bind(&RPCInstall));
return "Crown install started. \nRun 'crown-cli update status' to check download status.";
}
return "";
}
......@@ -2,8 +2,6 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "updater.h"
#define CURL_STATICLIB
#include "curl/curl.h"
#include "clientversion.h"
#include "util.h"
......@@ -14,7 +12,7 @@
struct myprogress {
double lastruntime;
CURL *curl;
void(*progressFunction)(int, int);
void(*progressFunction)(curl_off_t, curl_off_t);
};
// Global updater instance
......@@ -28,7 +26,6 @@ Updater::Updater() :
stopDownload(false)
{
SetOS();
GetUpdateInfo();
}
void Updater::SetOS()
......@@ -83,8 +80,9 @@ bool Updater::NeedToBeUpdated()
return false;
}
void Updater::GetUpdateInfo()
bool Updater::LoadUpdateInfo()
{
bool result = false;
CURL *curl;
std::string updateData;
CURLcode res = CURLE_FAILED_INIT;
......@@ -92,14 +90,12 @@ void Updater::GetUpdateInfo()
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, updaterInfoUrl.c_str());
// Diable cache
curl_easy_setopt(curl, CURLOPT_DNS_CACHE_TIMEOUT, 0);
curl_easy_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, GetUpdateData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &updateData);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
if (res == CURLE_OK)
{
jsonData = ParseJson(updateData);
......@@ -111,15 +107,22 @@ void Updater::GetUpdateInfo()
// There is an update
status = true;
}
result = true;
}
else
{
LogPrintf("Updater::GetUpdateInfo() - Error! Couldn't get data json. Error code - %d\n", res);
result = false;
}
return result;
}
std::string Updater::GetOsString(Updater::OS os)
{
if (os == UNKNOWN)
{
os = this->os;
}
std::string result = "Unknown";
switch(os) {
case Updater::LINUX_32:
......@@ -185,10 +188,24 @@ int Updater::GetVersionFromJson()
std::string Updater::GetDownloadUrl(Updater::OS version)
{
if (version == UNKNOWN)
{
version = os;
}
Value json = find_value(jsonData.get_obj(), GetOsString(version));
return GetUrl(json);
}
std::string Updater::GetDownloadSha256Sum(Updater::OS version)
{
if (version == UNKNOWN)
{
version = os;
}
Value json = find_value(jsonData.get_obj(), GetOsString(version));
return GetSha256sum(json);
}
static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
size_t written = fwrite(ptr, size, nmemb, (FILE *)stream);
......@@ -204,7 +221,12 @@ static int xferinfo(void *p,
return updater.GetStopDownload();
}
void Updater::DownloadFile(std::string url, std::string fileName, void(progressFunction)(int, int))
void Updater::DownloadFileAsync(std::string url, std::string fileName, void(progressFunction)(curl_off_t, curl_off_t))
{
boost::thread t(boost::bind(&Updater::DownloadFile, this, url, fileName, progressFunction));
}
void Updater::DownloadFile(std::string url, std::string fileName, void(progressFunction)(curl_off_t, curl_off_t))
{
stopDownload = false;
CURL *curl_handle;
......@@ -236,3 +258,9 @@ void Updater::StopDownload()
{
stopDownload = true;
}
bool Updater::Check()
{
LoadUpdateInfo();
return status;
}
......@@ -6,6 +6,8 @@
#define UPDATER_H
#include <iostream>
#define CURL_STATICLIB
#include "curl/curl.h"
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_utils.h"
......@@ -30,10 +32,7 @@ public:
MAC_OS,
};
Updater();
bool GetStatus()
{
return status;
}
bool Check();
int GetVersion()
{
return version;
......@@ -42,21 +41,23 @@ public:
{
return os;
}
void DownloadFile(std::string url, std::string fileName, void(progressFunction)(int, int));
void DownloadFile(std::string url, std::string fileName, void(progressFunction)(curl_off_t, curl_off_t));
void DownloadFileAsync(std::string url, std::string fileName, void(progressFunction)(curl_off_t, curl_off_t));
void StopDownload();
std::string GetDownloadUrl(Updater::OS version);
std::string GetDownloadUrl(Updater::OS version = UNKNOWN);
std::string GetDownloadSha256Sum(Updater::OS version = UNKNOWN);
std::string GetOsString(Updater::OS os = UNKNOWN);
bool GetStopDownload()
{
return stopDownload;
}
private:
std::string updaterInfoUrl;
void GetUpdateInfo();
bool LoadUpdateInfo();
Value ParseJson(std::string info);
void SetOS();
bool NeedToBeUpdated();
int GetVersionFromJson();
std::string GetOsString(Updater::OS os);
std::string GetUrl(Value value);
std::string GetSha256sum(Value value);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment