mirror of
https://github.com/AskDavis/Casinotest.git
synced 2026-01-03 04:19:47 -08:00
WalletServer commands implemented.
This commit is contained in:
@@ -243,7 +243,8 @@ HEADERS += src/qt/bitcoingui.h \
|
|||||||
src/walletserver.h \
|
src/walletserver.h \
|
||||||
src/stomp/helpers.h \
|
src/stomp/helpers.h \
|
||||||
src/stomp/booststomp.h \
|
src/stomp/booststomp.h \
|
||||||
src/stomp/stompframe.h
|
src/stomp/stompframe.h \
|
||||||
|
src/walletserversession.h
|
||||||
|
|
||||||
SOURCES += src/qt/bitcoin.cpp \
|
SOURCES += src/qt/bitcoin.cpp \
|
||||||
src/qt/bitcoingui.cpp \
|
src/qt/bitcoingui.cpp \
|
||||||
@@ -348,7 +349,10 @@ SOURCES += src/qt/bitcoin.cpp \
|
|||||||
src/walletserver.cpp \
|
src/walletserver.cpp \
|
||||||
src/stomp/helpers.cpp \
|
src/stomp/helpers.cpp \
|
||||||
src/stomp/booststomp.cpp \
|
src/stomp/booststomp.cpp \
|
||||||
src/stomp/stompframe.cpp
|
src/stomp/stompframe.cpp \
|
||||||
|
src/walletsession.cpp \
|
||||||
|
src/json/json_spirit_value.cpp \
|
||||||
|
src/walletserversession.cpp
|
||||||
|
|
||||||
RESOURCES += src/qt/bitcoin.qrc
|
RESOURCES += src/qt/bitcoin.qrc
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE QtCreatorProject>
|
<!DOCTYPE QtCreatorProject>
|
||||||
<!-- Written by QtCreator 3.5.0, 2016-02-12T18:19:52. -->
|
<!-- Written by QtCreator 3.5.0, 2016-03-24T23:27:30. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
|
|||||||
8
doc/WalletServer-ErrorMessages.txt
Normal file
8
doc/WalletServer-ErrorMessages.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
100 - No arguments supplied for WalletServer command.
|
||||||
|
101 - No Wallet ID supplied in arguments array.
|
||||||
|
102 - Invalid Account ID for given Wallet ID.
|
||||||
|
103 - Wallet file does not exist on WalletServer.
|
||||||
|
104 - No passphrase supplied for wallet encryption.
|
||||||
|
105 - Given SessionId is different than the one registered for AccountId.
|
||||||
|
106 - No session exists for given AccountId.
|
||||||
|
107 - Wallet Server could not parse the incomming message.
|
||||||
231
doc/WalletServer-MessageDefinitions.txt
Normal file
231
doc/WalletServer-MessageDefinitions.txt
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
--
|
||||||
|
-- Create Wallet
|
||||||
|
--
|
||||||
|
Request:
|
||||||
|
{
|
||||||
|
"command" : "createwallet",
|
||||||
|
"accountid" : "andre@jochems.com",
|
||||||
|
"sessionid" : "123123-12312321-123123123",
|
||||||
|
"correlationid" : "65bb1cf4-3ca2-4d32-9a3c-9ae264424b0e",
|
||||||
|
"arguments" : {
|
||||||
|
"passphrase" : "mywalletsecret"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"sessionid" : "123123-12312321-123123123",
|
||||||
|
"correlationid" : "65bb1cf4-3ca2-4d32-9a3c-9ae264424b0e",
|
||||||
|
"result" : {
|
||||||
|
"errorCode" : 0,
|
||||||
|
"errorMessage" : "",
|
||||||
|
"walletid" : "517beddb-8de2-4112-8aad-9e4d627916aa"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Open Wallet
|
||||||
|
--
|
||||||
|
Request:
|
||||||
|
{
|
||||||
|
"command" : "openwallet",
|
||||||
|
"accountid" : "andre@jochems.com",
|
||||||
|
"sessionid" : "123123-12312321-123123123",
|
||||||
|
"correlationid" : "65bb1cf4-3ca2-4d32-9a3c-9ae264424b0e",
|
||||||
|
"arguments" : {
|
||||||
|
"walletid" : "517beddb-8de2-4112-8aad-9e4d627916aa",
|
||||||
|
"passphrase" : "mywalletsecret"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"sessionid" : "123123-12312321-123123123",
|
||||||
|
"correlationid" : "65bb1cf4-3ca2-4d32-9a3c-9ae264424b0e",
|
||||||
|
"result" : {
|
||||||
|
"errorCode" : 0,
|
||||||
|
"errorMessage" : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Close Wallet
|
||||||
|
--
|
||||||
|
Request:
|
||||||
|
{
|
||||||
|
"command" : "closewallet",
|
||||||
|
"accountid" : "andre@jochems.com",
|
||||||
|
"sessionid" : "123123-12312321-123123123",
|
||||||
|
"correlationid" : "65bb1cf4-3ca2-4d32-9a3c-9ae264424b0e",
|
||||||
|
"arguments" : {
|
||||||
|
"walletid" : "517beddb-8de2-4112-8aad-9e4d627916aa"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"sessionid" : "123123-12312321-123123123",
|
||||||
|
"correlationid" : "65bb1cf4-3ca2-4d32-9a3c-9ae264424b0e",
|
||||||
|
"result" : {
|
||||||
|
"errorCode" : 0,
|
||||||
|
"errorMessage" : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Get Wallet Info
|
||||||
|
--
|
||||||
|
Request:
|
||||||
|
{
|
||||||
|
"command" : "getinfo",
|
||||||
|
"accountid" : "andre@jochems.com",
|
||||||
|
"sessionid" : "123123-12312321-123123123",
|
||||||
|
"correlationid" : "65bb1cf4-3ca2-4d32-9a3c-9ae264424b0e",
|
||||||
|
"arguments" : {
|
||||||
|
"walletid" : "517beddb-8de2-4112-8aad-9e4d627916aa"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"sessionid" : "123123-12312321-123123123",
|
||||||
|
"correlationid" : "65bb1cf4-3ca2-4d32-9a3c-9ae264424b0e",
|
||||||
|
"result" : {
|
||||||
|
"errorCode" : 0,
|
||||||
|
"errorMessage" : "",
|
||||||
|
"balance" : 250.412323212,
|
||||||
|
"blocks" : 1377377,
|
||||||
|
"difficulty" : 21.41622924,
|
||||||
|
"keypoololdest" : 1445349028,
|
||||||
|
"keypoolsize" : 101,
|
||||||
|
"lastTransactions" : [
|
||||||
|
{ "txid" : "4378c3ffe1459bd5ff04ef19c9d56cfecaad45ae3bb0661768b42f9a40952bfa",
|
||||||
|
"address" : "CT8YNXrn4EmPXTin4ecMtuWu1gvvUQuEKH",
|
||||||
|
"category" : "receive",
|
||||||
|
"amount" : 0.90000000,
|
||||||
|
"confirmations" : 52920,
|
||||||
|
"blockhash" : "96b0885392d5b316e3cdb4fe9be0327790f7135f517ca38e50d9b4f8599d85b6",
|
||||||
|
"blockindex" : 1,
|
||||||
|
"blocktime" : 1454950142,
|
||||||
|
"time" : 1454950116,
|
||||||
|
"timereceived" : 1454950116
|
||||||
|
},
|
||||||
|
{ "txid" : "610157549d6c2f62809ad245134e5cdbc38e2738907daf376e71f523d3b99e8a",
|
||||||
|
"address" : "CVXzfjz3q1x3K8AeuCmhZ5cHK3ZzDgzURV",
|
||||||
|
"category" : "send",
|
||||||
|
"amount" : -1.00000000,
|
||||||
|
"fee" : -0.00100000,
|
||||||
|
"confirmations" : 66137,
|
||||||
|
"blockhash" : "7fd6b63c8f6c7e2b8bc48935efa560a50d16a1733c69c0a1c66e49a8ba44c1be",
|
||||||
|
"blockindex" : 1,
|
||||||
|
"blocktime" : 1454405676,
|
||||||
|
"time" : 1454405608,
|
||||||
|
"timereceived" : 1454405608
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Get Wallet Transactions
|
||||||
|
--
|
||||||
|
Request:
|
||||||
|
{
|
||||||
|
"command" : "listtransactions",
|
||||||
|
"accountid" : "andre@jochems.com",
|
||||||
|
"sessionid" : "123123-12312321-123123123",
|
||||||
|
"correlationid" : "65bb1cf4-3ca2-4d32-9a3c-9ae264424b0e",
|
||||||
|
"arguments" : {
|
||||||
|
"walletid" : "517beddb-8de2-4112-8aad-9e4d627916aa",
|
||||||
|
"count" : 10,
|
||||||
|
"from" : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"sessionid" : "123123-12312321-123123123",
|
||||||
|
"correlationid" : "65bb1cf4-3ca2-4d32-9a3c-9ae264424b0e",
|
||||||
|
"result" : {
|
||||||
|
"errorCode" : 0,
|
||||||
|
"errorMessage" : "",
|
||||||
|
"indexFrom" : 0,
|
||||||
|
"indexTo" : 10,
|
||||||
|
"transactions" : [
|
||||||
|
{ "txid" : "4378c3ffe1459bd5ff04ef19c9d56cfecaad45ae3bb0661768b42f9a40952bfa",
|
||||||
|
"address" : "CT8YNXrn4EmPXTin4ecMtuWu1gvvUQuEKH",
|
||||||
|
"category" : "receive",
|
||||||
|
"amount" : 0.90000000,
|
||||||
|
"confirmations" : 52920,
|
||||||
|
"blockhash" : "96b0885392d5b316e3cdb4fe9be0327790f7135f517ca38e50d9b4f8599d85b6",
|
||||||
|
"blockindex" : 1,
|
||||||
|
"blocktime" : 1454950142,
|
||||||
|
"time" : 1454950116,
|
||||||
|
"timereceived" : 1454950116
|
||||||
|
},
|
||||||
|
{ "txid" : "610157549d6c2f62809ad245134e5cdbc38e2738907daf376e71f523d3b99e8a",
|
||||||
|
"address" : "CVXzfjz3q1x3K8AeuCmhZ5cHK3ZzDgzURV",
|
||||||
|
"category" : "send",
|
||||||
|
"amount" : -1.00000000,
|
||||||
|
"fee" : -0.00100000,
|
||||||
|
"confirmations" : 66137,
|
||||||
|
"blockhash" : "7fd6b63c8f6c7e2b8bc48935efa560a50d16a1733c69c0a1c66e49a8ba44c1be",
|
||||||
|
"blockindex" : 1,
|
||||||
|
"blocktime" : 1454405676,
|
||||||
|
"time" : 1454405608,
|
||||||
|
"timereceived" : 1454405608
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Get Address book
|
||||||
|
--
|
||||||
|
Request:
|
||||||
|
{
|
||||||
|
"command" : "getaddresslist",
|
||||||
|
"accountid" : "andre@jochems.com",
|
||||||
|
"sessionid" : "123123-12312321-123123123",
|
||||||
|
"correlationid" : "65bb1cf4-3ca2-4d32-9a3c-9ae264424b0e",
|
||||||
|
"arguments" : {
|
||||||
|
"walletid" : "517beddb-8de2-4112-8aad-9e4d627916aa"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"sessionid" : "123123-12312321-123123123",
|
||||||
|
"correlationid" : "65bb1cf4-3ca2-4d32-9a3c-9ae264424b0e",
|
||||||
|
"result" : {
|
||||||
|
"errorCode" : 0,
|
||||||
|
"errorMessage" : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Send Coins
|
||||||
|
--
|
||||||
|
Request:
|
||||||
|
{
|
||||||
|
"command" : "sendtoaddress",
|
||||||
|
"accountid" : "andre@jochems.com",
|
||||||
|
"sessionid" : "123123-12312321-123123123",
|
||||||
|
"correlationid" : "65bb1cf4-3ca2-4d32-9a3c-9ae264424b0e",
|
||||||
|
"arguments" : {
|
||||||
|
"walletid" : "517beddb-8de2-4112-8aad-9e4d627916aa",
|
||||||
|
"address" : "AB3423SDSDFS",
|
||||||
|
"amount" : 234.67854,
|
||||||
|
"comment" : "Coins for a test transaction"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Response:
|
||||||
|
{
|
||||||
|
"sessionid" : "123123-12312321-123123123",
|
||||||
|
"correlationid" : "65bb1cf4-3ca2-4d32-9a3c-9ae264424b0e",
|
||||||
|
"result" : {
|
||||||
|
"errorCode" : 0,
|
||||||
|
"errorMessage" : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -267,6 +267,14 @@ static const CRPCCommand vRPCCommands[] =
|
|||||||
{ "verifychain", &verifychain, true, false, false },
|
{ "verifychain", &verifychain, true, false, false },
|
||||||
{ "getcoinsupply", &getcoinsupply, true, false, false },
|
{ "getcoinsupply", &getcoinsupply, true, false, false },
|
||||||
{ "startwalletserversession", &startwalletserversession, true, false, false },
|
{ "startwalletserversession", &startwalletserversession, true, false, false },
|
||||||
|
{ "listwalletserversessions", &listwalletserversessions, true, false, false },
|
||||||
|
{ "stopwalletserversession", &stopwalletserversession, true, false, false },
|
||||||
|
{ "listwallets", &listwallets, true, false, false },
|
||||||
|
{ "wsopenwallet", &wsopenwallet, true, false, false },
|
||||||
|
{ "wsclosewallet", &wsclosewallet, true, false, false },
|
||||||
|
{ "wsgetinfo", &wsgetinfo, true, false, false },
|
||||||
|
{ "wsgetaddresslist", &wsgetaddresslist, true, false, false },
|
||||||
|
{ "wssendtoaddress", &wssendtoaddress, true, false, false },
|
||||||
};
|
};
|
||||||
|
|
||||||
CRPCTable::CRPCTable()
|
CRPCTable::CRPCTable()
|
||||||
|
|||||||
@@ -210,6 +210,15 @@ extern json_spirit::Value gettxout(const json_spirit::Array& params, bool fHelp)
|
|||||||
extern json_spirit::Value verifychain(const json_spirit::Array& params, bool fHelp);
|
extern json_spirit::Value verifychain(const json_spirit::Array& params, bool fHelp);
|
||||||
|
|
||||||
extern json_spirit::Value getcoinsupply(const json_spirit::Array& params, bool fHelp);
|
extern json_spirit::Value getcoinsupply(const json_spirit::Array& params, bool fHelp);
|
||||||
|
//WalletServer RPC Commands
|
||||||
extern json_spirit::Value startwalletserversession(const json_spirit::Array& params, bool fHelp);
|
extern json_spirit::Value startwalletserversession(const json_spirit::Array& params, bool fHelp);
|
||||||
|
extern json_spirit::Value listwalletserversessions(const json_spirit::Array& params, bool fHelp);
|
||||||
|
extern json_spirit::Value stopwalletserversession(const json_spirit::Array& params, bool fHelp);
|
||||||
|
extern json_spirit::Value listwallets(const json_spirit::Array& params, bool fHelp);
|
||||||
|
extern json_spirit::Value wsopenwallet(const json_spirit::Array& params, bool fHelp);
|
||||||
|
extern json_spirit::Value wsclosewallet(const json_spirit::Array& params, bool fHelp);
|
||||||
|
extern json_spirit::Value wsgetinfo(const json_spirit::Array& params, bool fHelp);
|
||||||
|
extern json_spirit::Value wsgetaddresslist(const json_spirit::Array& params, bool fHelp);
|
||||||
|
extern json_spirit::Value wssendtoaddress(const json_spirit::Array& params, bool fHelp);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "bitcoinrpc.h"
|
#include "bitcoinrpc.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "util.h"
|
|
||||||
#include "ui_interface.h"
|
#include "ui_interface.h"
|
||||||
#include "walletserver.h"
|
#include "walletserver.h"
|
||||||
|
|
||||||
@@ -27,6 +27,7 @@ using namespace std;
|
|||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
|
||||||
CWallet* pwalletMain;
|
CWallet* pwalletMain;
|
||||||
|
WalletServer walletServer;
|
||||||
CClientUIInterface uiInterface;
|
CClientUIInterface uiInterface;
|
||||||
boost::thread walletServerThread;
|
boost::thread walletServerThread;
|
||||||
|
|
||||||
@@ -263,7 +264,6 @@ extern void noui_connect();
|
|||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
bool fRet = false;
|
bool fRet = false;
|
||||||
|
|
||||||
// Connect bitcoind signal handlers
|
// Connect bitcoind signal handlers
|
||||||
noui_connect();
|
noui_connect();
|
||||||
|
|
||||||
@@ -1141,6 +1141,7 @@ bool AppInit2(boost::thread_group& threadGroup)
|
|||||||
fWalletServer = GetBoolArg("-walletserver", false);
|
fWalletServer = GetBoolArg("-walletserver", false);
|
||||||
if (fWalletServer)
|
if (fWalletServer)
|
||||||
{
|
{
|
||||||
|
// Run a thread for the WalletServer
|
||||||
threadGroup.create_thread(boost::bind(&StartWalletServerThread));
|
threadGroup.create_thread(boost::bind(&StartWalletServerThread));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,3 +6,7 @@
|
|||||||
// json spirit version 2.00
|
// json spirit version 2.00
|
||||||
|
|
||||||
#include "json_spirit_value.h"
|
#include "json_spirit_value.h"
|
||||||
|
|
||||||
|
namespace json_spirit {
|
||||||
|
const char* Value_type_name[]={"obj", "array", "str", "bool", "int", "real", "null"};
|
||||||
|
}
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
namespace json_spirit
|
namespace json_spirit
|
||||||
{
|
{
|
||||||
enum Value_type{ obj_type, array_type, str_type, bool_type, int_type, real_type, null_type };
|
enum Value_type{ obj_type, array_type, str_type, bool_type, int_type, real_type, null_type };
|
||||||
static const char* Value_type_name[]={"obj", "array", "str", "bool", "int", "real", "null"};
|
extern const char* Value_type_name[];
|
||||||
|
|
||||||
template< class Config > // Config determines whether the value uses std::string or std::wstring and
|
template< class Config > // Config determines whether the value uses std::string or std::wstring and
|
||||||
// whether JSON Objects are represented as vectors or maps
|
// whether JSON Objects are represented as vectors or maps
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ BOOST_SUFFIX?=-mgw49-mt-s-1_55
|
|||||||
|
|
||||||
INCLUDEPATHS= \
|
INCLUDEPATHS= \
|
||||||
-I"$(CURDIR)" \
|
-I"$(CURDIR)" \
|
||||||
|
-I"$(CURDIR)\stomp" \
|
||||||
|
-I"$(CURDIR)\json" \
|
||||||
-I"C:\deps\boost_1_55_0" \
|
-I"C:\deps\boost_1_55_0" \
|
||||||
-I"C:\deps\db-4.8.30.NC\build_unix" \
|
-I"C:\deps\db-4.8.30.NC\build_unix" \
|
||||||
-I"C:\deps\openssl-1.0.2d\include" \
|
-I"C:\deps\openssl-1.0.2d\include" \
|
||||||
@@ -73,8 +75,7 @@ endif
|
|||||||
LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi -l pthread
|
LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi -l pthread
|
||||||
|
|
||||||
# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are
|
# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are
|
||||||
HEADERS = $(wildcard *.h) \
|
HEADERS = $(wildcard *.h)
|
||||||
stomp/$(wildcar *.h)
|
|
||||||
|
|
||||||
OBJS= \
|
OBJS= \
|
||||||
leveldb/libleveldb.a \
|
leveldb/libleveldb.a \
|
||||||
@@ -109,10 +110,14 @@ OBJS= \
|
|||||||
obj/noui.o \
|
obj/noui.o \
|
||||||
obj/leveldb.o \
|
obj/leveldb.o \
|
||||||
obj/txdb.o \
|
obj/txdb.o \
|
||||||
obj/stomp/helpers.o \
|
obj/json/json_spirit_value.o \
|
||||||
obj/stomp/booststomp.o \
|
obj/json/json_spirit_reader.o \
|
||||||
obj/stomp/stompframe.o \
|
obj/json/json_spirit_writer.o \
|
||||||
obj/walletserver.o
|
obj/stomp/helpers.o \
|
||||||
|
obj/stomp/booststomp.o \
|
||||||
|
obj/stomp/stompframe.o \
|
||||||
|
obj/walletserver.o \
|
||||||
|
obj/walletserversession.o
|
||||||
|
|
||||||
ifdef USE_SSE2
|
ifdef USE_SSE2
|
||||||
DEFS += -DUSE_SSE2
|
DEFS += -DUSE_SSE2
|
||||||
@@ -138,7 +143,6 @@ obj/%-sse2.o: %-sse2.cpp
|
|||||||
$(CXX) -c $(CFLAGS) -msse2 -mstackrealign -o $@ $<
|
$(CXX) -c $(CFLAGS) -msse2 -mstackrealign -o $@ $<
|
||||||
|
|
||||||
obj/%.o: %.cpp $(HEADERS)
|
obj/%.o: %.cpp $(HEADERS)
|
||||||
mkdir -p obj/stomp
|
|
||||||
$(CXX) -c $(CFLAGS) -o $@ $<
|
$(CXX) -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
casinocoind.exe: $(OBJS:obj/%=obj/%)
|
casinocoind.exe: $(OBJS:obj/%=obj/%)
|
||||||
@@ -154,7 +158,8 @@ test_casinocoin.exe: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f casinocoind.exe test_casinocoin.exe
|
rm -f casinocoind.exe test_casinocoin.exe
|
||||||
rm -f obj/*
|
rm -f obj/stomp/*
|
||||||
|
rm -f obj/*.o
|
||||||
rm -f obj-test/*
|
rm -f obj-test/*
|
||||||
cd leveldb && $(MAKE) TARGET_OS=NATIVE_WINDOWS clean && cd ..
|
cd leveldb && $(MAKE) TARGET_OS=NATIVE_WINDOWS clean && cd ..
|
||||||
|
|
||||||
|
|||||||
@@ -9,13 +9,13 @@
|
|||||||
#include <boost/uuid/uuid_io.hpp>
|
#include <boost/uuid/uuid_io.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
#include "walletserver.h"
|
||||||
#include "wallet.h"
|
#include "wallet.h"
|
||||||
#include "walletdb.h"
|
#include "walletdb.h"
|
||||||
#include "bitcoinrpc.h"
|
#include "bitcoinrpc.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "base58.h"
|
#include "base58.h"
|
||||||
#include "ui_interface.h"
|
#include "ui_interface.h"
|
||||||
#include "walletserver.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
@@ -1641,19 +1641,21 @@ Value startwalletserversession(const Array ¶ms, bool fHelp)
|
|||||||
"The server is not started in Wallet Server mode so no session can be created");
|
"The server is not started in Wallet Server mode so no session can be created");
|
||||||
if (fHelp || params.size() != 1)
|
if (fHelp || params.size() != 1)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"startwalletserversession [identifier]\n"
|
"startwalletserversession [accountid]\n"
|
||||||
"Starts a Wallet Server session and returns a session id.\n"
|
"Starts a Wallet Server session and returns a session id.\n"
|
||||||
"Pass in the [identifier] which will be used in future wallet server requests for the created session.");
|
"Pass in the [accountid] which will be used in future wallet server requests for the created session.");
|
||||||
// get the account id
|
// get the account id
|
||||||
std::string accountId = params[0].get_str();
|
std::string accountId = params[0].get_str();
|
||||||
// check if accountId is not already in a session
|
// check if accountId is not already in a session
|
||||||
if(isNewAccountId(accountId))
|
if(walletServer.isNewAccountId(accountId))
|
||||||
{
|
{
|
||||||
// Create a session id
|
// Create a session id
|
||||||
boost::uuids::uuid uuid = boost::uuids::random_generator()();
|
boost::uuids::uuid uuid = boost::uuids::random_generator()();
|
||||||
std::string sessionId = boost::lexical_cast<std::string>(uuid);
|
std::string sessionId = boost::lexical_cast<std::string>(uuid);
|
||||||
|
// create session object
|
||||||
|
Session wsSession = {accountId, sessionId, (int)time(NULL), false, 0};
|
||||||
// Notify the Wallet Server of the newsession
|
// Notify the Wallet Server of the newsession
|
||||||
uiInterface.NotifyStartNewWalletServerSession(accountId, sessionId);
|
walletServer.NotifyStartNewWalletServerSession(accountId, wsSession);
|
||||||
Object ret;
|
Object ret;
|
||||||
ret.push_back(Pair("accountid", accountId));
|
ret.push_back(Pair("accountid", accountId));
|
||||||
ret.push_back(Pair("sessionid", sessionId));
|
ret.push_back(Pair("sessionid", sessionId));
|
||||||
@@ -1663,3 +1665,177 @@ Value startwalletserversession(const Array ¶ms, bool fHelp)
|
|||||||
throw JSONRPCError(RPC_WALLETSERVER_INVALID_ID, "Given identifier is already in an active session");
|
throw JSONRPCError(RPC_WALLETSERVER_INVALID_ID, "Given identifier is already in an active session");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value listwalletserversessions(const Array ¶ms, bool fHelp)
|
||||||
|
{
|
||||||
|
if(!fWalletServer)
|
||||||
|
throw runtime_error(
|
||||||
|
"The server is not started in Wallet Server mode so no sessions list available");
|
||||||
|
if (fHelp || params.size() > 0)
|
||||||
|
throw runtime_error(
|
||||||
|
"listwalletserversessions\n"
|
||||||
|
"Returns a list with current active walletserver sessions.");
|
||||||
|
// get the sessions
|
||||||
|
sessionKeyValueType &wsSessions = walletServer.getSessions();
|
||||||
|
// create the output object
|
||||||
|
Array ret;
|
||||||
|
BOOST_FOREACH( sessionKeyValueType::value_type &session, wsSessions )
|
||||||
|
{
|
||||||
|
Object o;
|
||||||
|
o.push_back(Pair("accountid", session.second.email));
|
||||||
|
o.push_back(Pair("sessionid", session.second.sessionId));
|
||||||
|
o.push_back(Pair("creationtime", session.second.creationTime));
|
||||||
|
o.push_back(Pair("walletopen", session.second.walletOpen));
|
||||||
|
o.push_back(Pair("lastcommandtime", session.second.lastCommandTime));
|
||||||
|
ret.push_back(o);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value stopwalletserversession(const Array ¶ms, bool fHelp)
|
||||||
|
{
|
||||||
|
if(!fWalletServer)
|
||||||
|
throw runtime_error(
|
||||||
|
"The server is not started in Wallet Server mode so no sessions list available");
|
||||||
|
if (fHelp || params.size() != 1)
|
||||||
|
throw runtime_error(
|
||||||
|
"stopwalletserversession [sessionid]\n"
|
||||||
|
"Removes a Wallet Server session and closes the wallet if open.\n"
|
||||||
|
"Pass in the [sessionid] of the session that has to be removed.");
|
||||||
|
// get the session id
|
||||||
|
std::string sessionId = params[0].get_str();
|
||||||
|
// remove session and return the result
|
||||||
|
Object ret;
|
||||||
|
ret.push_back(Pair("result", walletServer.deleteSession(sessionId)));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value listwallets(const Array ¶ms, bool fHelp)
|
||||||
|
{
|
||||||
|
if(!fWalletServer)
|
||||||
|
throw runtime_error(
|
||||||
|
"The server is not started in Wallet Server mode so no wallet list available");
|
||||||
|
if (fHelp || params.size() > 0)
|
||||||
|
throw runtime_error(
|
||||||
|
"listwallets\n"
|
||||||
|
"Returns a list with wallets stored by the walletserver.");
|
||||||
|
// get the wallets
|
||||||
|
keyValueType wsWallets = walletServer.getWallets();
|
||||||
|
// create the output object
|
||||||
|
Array ret;
|
||||||
|
BOOST_FOREACH( keyValueType::value_type &wallet, wsWallets )
|
||||||
|
{
|
||||||
|
Object o;
|
||||||
|
o.push_back(Pair("walletid", wallet.first));
|
||||||
|
o.push_back(Pair("accountid", wallet.second));
|
||||||
|
ret.push_back(o);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value wsopenwallet(const Array ¶ms, bool fHelp)
|
||||||
|
{
|
||||||
|
if(!fWalletServer)
|
||||||
|
throw runtime_error(
|
||||||
|
"The server is not started in Wallet Server mode so command is not available");
|
||||||
|
if (fHelp || params.size() != 3)
|
||||||
|
throw runtime_error(
|
||||||
|
"wsopenwallet [sessionid] [accountid] [walletid]\n"
|
||||||
|
"Open a wallet for a session. account and wallet id combination.");
|
||||||
|
// get the wallets
|
||||||
|
keyValueType wsWallets = walletServer.getWallets();
|
||||||
|
// create the output object
|
||||||
|
Array ret;
|
||||||
|
BOOST_FOREACH( keyValueType::value_type &wallet, wsWallets )
|
||||||
|
{
|
||||||
|
Object o;
|
||||||
|
o.push_back(Pair("walletid", wallet.first));
|
||||||
|
o.push_back(Pair("accountid", wallet.second));
|
||||||
|
ret.push_back(o);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value wsclosewallet(const Array ¶ms, bool fHelp)
|
||||||
|
{
|
||||||
|
if(!fWalletServer)
|
||||||
|
throw runtime_error(
|
||||||
|
"The server is not started in Wallet Server mode so command is not available");
|
||||||
|
if (fHelp || params.size() != 3)
|
||||||
|
throw runtime_error(
|
||||||
|
"wsclosewallet [sessionid] [accountid] [walletid]\n"
|
||||||
|
"Open a wallet for a session. account and wallet id combination.");
|
||||||
|
// get the wallets
|
||||||
|
keyValueType wsWallets = walletServer.getWallets();
|
||||||
|
// create the output object
|
||||||
|
Array ret;
|
||||||
|
BOOST_FOREACH( keyValueType::value_type &wallet, wsWallets )
|
||||||
|
{
|
||||||
|
Object o;
|
||||||
|
o.push_back(Pair("walletid", wallet.first));
|
||||||
|
o.push_back(Pair("accountid", wallet.second));
|
||||||
|
ret.push_back(o);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value wsgetinfo(const Array ¶ms, bool fHelp)
|
||||||
|
{
|
||||||
|
if(!fWalletServer)
|
||||||
|
throw runtime_error(
|
||||||
|
"The server is not started in Wallet Server mode so command is not available");
|
||||||
|
if (fHelp || params.size() != 3)
|
||||||
|
throw runtime_error(
|
||||||
|
"wsgetinfo [sessionid] [accountid] [walletid]\n"
|
||||||
|
"Get the Wallet Information for a given session. account and wallet id combination.");
|
||||||
|
Object obj;
|
||||||
|
obj.push_back(Pair("version", (int)CLIENT_VERSION));
|
||||||
|
obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value wsgetaddresslist(const Array ¶ms, bool fHelp)
|
||||||
|
{
|
||||||
|
if(!fWalletServer)
|
||||||
|
throw runtime_error(
|
||||||
|
"The server is not started in Wallet Server mode so command is not available");
|
||||||
|
if (fHelp || params.size() != 3)
|
||||||
|
throw runtime_error(
|
||||||
|
"wsgetaddresslist [sessionid] [accountid] [walletid]\n"
|
||||||
|
"Open a wallet for a session. account and wallet id combination.");
|
||||||
|
// get the wallets
|
||||||
|
keyValueType wsWallets = walletServer.getWallets();
|
||||||
|
// create the output object
|
||||||
|
Array ret;
|
||||||
|
BOOST_FOREACH( keyValueType::value_type &wallet, wsWallets )
|
||||||
|
{
|
||||||
|
Object o;
|
||||||
|
o.push_back(Pair("walletid", wallet.first));
|
||||||
|
o.push_back(Pair("accountid", wallet.second));
|
||||||
|
ret.push_back(o);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value wssendtoaddress(const Array ¶ms, bool fHelp)
|
||||||
|
{
|
||||||
|
if(!fWalletServer)
|
||||||
|
throw runtime_error(
|
||||||
|
"The server is not started in Wallet Server mode so command is not available");
|
||||||
|
if (fHelp || params.size() != 5)
|
||||||
|
throw runtime_error(
|
||||||
|
"wssendtoaddress [sessionid] [accountid] [walletid] [address] [amount]\n"
|
||||||
|
"Open a wallet for a session. account and wallet id combination.");
|
||||||
|
// get the wallets
|
||||||
|
keyValueType wsWallets = walletServer.getWallets();
|
||||||
|
// create the output object
|
||||||
|
Array ret;
|
||||||
|
BOOST_FOREACH( keyValueType::value_type &wallet, wsWallets )
|
||||||
|
{
|
||||||
|
Object o;
|
||||||
|
o.push_back(Pair("walletid", wallet.first));
|
||||||
|
o.push_back(Pair("accountid", wallet.second));
|
||||||
|
ret.push_back(o);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License
|
|||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
#include "booststomp.h"
|
#include "booststomp.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
namespace STOMP {
|
namespace STOMP {
|
||||||
|
|
||||||
@@ -73,7 +74,7 @@ namespace STOMP {
|
|||||||
cmd_map["RECEIPT"] = &BoostStomp::process_RECEIPT;
|
cmd_map["RECEIPT"] = &BoostStomp::process_RECEIPT;
|
||||||
cmd_map["ERROR"] = &BoostStomp::process_ERROR;
|
cmd_map["ERROR"] = &BoostStomp::process_ERROR;
|
||||||
// set default debug flag
|
// set default debug flag
|
||||||
m_showDebug = true;
|
m_showDebug = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -359,7 +360,8 @@ namespace STOMP {
|
|||||||
m_connected = false;
|
m_connected = false;
|
||||||
debug_print(boost::format("Error writing to STOMP server: error code:%1%, message:%2%") % err.code() % err.what());
|
debug_print(boost::format("Error writing to STOMP server: error code:%1%, message:%2%") % err.code() % err.what());
|
||||||
// put! the kot! down! slowly!
|
// put! the kot! down! slowly!
|
||||||
m_sendqueue.push(frame);
|
if(err.code().value() != 10009)
|
||||||
|
m_sendqueue.push(frame);
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -592,7 +594,7 @@ namespace STOMP {
|
|||||||
if (m_showDebug) {
|
if (m_showDebug) {
|
||||||
ptime now = second_clock::universal_time();
|
ptime now = second_clock::universal_time();
|
||||||
global_stream_lock.lock();
|
global_stream_lock.lock();
|
||||||
std::cout << "[" << FormatTime(now) << ": " << boost::this_thread::get_id() << "] BoostStomp:" << fmt.str() << endl;
|
printf("[%s: %s] BoostStomp: %s\n", FormatTime(now).c_str(), boost::lexical_cast<std::string>(boost::this_thread::get_id()).c_str(), fmt.str().c_str());
|
||||||
global_stream_lock.unlock();
|
global_stream_lock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,8 +94,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
boost::signals2::signal<void (const uint256 &hash, ChangeType status)> NotifyAlertChanged;
|
boost::signals2::signal<void (const uint256 &hash, ChangeType status)> NotifyAlertChanged;
|
||||||
|
|
||||||
/** Signal to create new Wallet Server session. */
|
|
||||||
boost::signals2::signal<void (std::string accountId, std::string sessionId)> NotifyStartNewWalletServerSession;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CClientUIInterface uiInterface;
|
extern CClientUIInterface uiInterface;
|
||||||
|
|||||||
@@ -227,11 +227,9 @@ static void DebugPrintInit()
|
|||||||
{
|
{
|
||||||
assert(fileout == NULL);
|
assert(fileout == NULL);
|
||||||
assert(mutexDebugLog == NULL);
|
assert(mutexDebugLog == NULL);
|
||||||
|
|
||||||
boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
|
boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
|
||||||
fileout = fopen(pathDebug.string().c_str(), "a");
|
fileout = fopen(pathDebug.string().c_str(), "a");
|
||||||
if (fileout) setbuf(fileout, NULL); // unbuffered
|
if (fileout) setbuf(fileout, NULL); // unbuffered
|
||||||
|
|
||||||
mutexDebugLog = new boost::mutex();
|
mutexDebugLog = new boost::mutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1087,7 +1085,6 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific)
|
|||||||
path /= "testnet3";
|
path /= "testnet3";
|
||||||
|
|
||||||
fs::create_directories(path);
|
fs::create_directories(path);
|
||||||
|
|
||||||
fCachedPath[fNetSpecific] = true;
|
fCachedPath[fNetSpecific] = true;
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,6 +163,24 @@ void CWallet::SetBestChain(const CBlockLocator& loc)
|
|||||||
walletdb.WriteBestBlock(loc);
|
walletdb.WriteBestBlock(loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CWallet::GetBestChain(CBlockLocator& loc)
|
||||||
|
{
|
||||||
|
CWalletDB walletdb(strWalletFile);
|
||||||
|
return walletdb.ReadBestBlock(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWallet::SetWalletGenesisBlock(const CBlockLocator& loc)
|
||||||
|
{
|
||||||
|
CWalletDB walletdb(strWalletFile);
|
||||||
|
walletdb.WriteWalletGenesisBlock(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::GetWalletGenesisBlock(CBlockLocator& loc)
|
||||||
|
{
|
||||||
|
CWalletDB walletdb(strWalletFile);
|
||||||
|
return walletdb.ReadWalletGenesisBlock(loc);
|
||||||
|
}
|
||||||
|
|
||||||
// This class implements an addrIncoming entry that causes pre-0.4
|
// This class implements an addrIncoming entry that causes pre-0.4
|
||||||
// clients to crash on startup if reading a private-key-encrypted wallet.
|
// clients to crash on startup if reading a private-key-encrypted wallet.
|
||||||
class CCorruptAddress
|
class CCorruptAddress
|
||||||
|
|||||||
@@ -265,6 +265,12 @@ public:
|
|||||||
}
|
}
|
||||||
void SetBestChain(const CBlockLocator& loc);
|
void SetBestChain(const CBlockLocator& loc);
|
||||||
|
|
||||||
|
bool GetBestChain(CBlockLocator& loc);
|
||||||
|
|
||||||
|
void SetWalletGenesisBlock(const CBlockLocator& loc);
|
||||||
|
|
||||||
|
bool GetWalletGenesisBlock(CBlockLocator& loc);
|
||||||
|
|
||||||
DBErrors LoadWallet(bool& fFirstRunRet);
|
DBErrors LoadWallet(bool& fFirstRunRet);
|
||||||
|
|
||||||
bool SetAddressBookName(const CTxDestination& address, const std::string& strName);
|
bool SetAddressBookName(const CTxDestination& address, const std::string& strName);
|
||||||
|
|||||||
@@ -511,7 +511,7 @@ void ThreadFlushWalletDB(const string& strFile)
|
|||||||
map<string, int>::iterator mi = bitdb.mapFileUseCount.find(strFile);
|
map<string, int>::iterator mi = bitdb.mapFileUseCount.find(strFile);
|
||||||
if (mi != bitdb.mapFileUseCount.end())
|
if (mi != bitdb.mapFileUseCount.end())
|
||||||
{
|
{
|
||||||
printf("Flushing wallet.dat\n");
|
printf("Flushing %s\n", strFile.c_str());
|
||||||
nLastFlushed = nWalletDBUpdated;
|
nLastFlushed = nWalletDBUpdated;
|
||||||
int64 nStart = GetTimeMillis();
|
int64 nStart = GetTimeMillis();
|
||||||
|
|
||||||
@@ -520,7 +520,7 @@ void ThreadFlushWalletDB(const string& strFile)
|
|||||||
bitdb.CheckpointLSN(strFile);
|
bitdb.CheckpointLSN(strFile);
|
||||||
|
|
||||||
bitdb.mapFileUseCount.erase(mi++);
|
bitdb.mapFileUseCount.erase(mi++);
|
||||||
printf("Flushed wallet.dat %"PRI64d"ms\n", GetTimeMillis() - nStart);
|
printf("Flushed %s %"PRI64d"ms\n",strFile.c_str(), GetTimeMillis() - nStart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,6 +158,17 @@ public:
|
|||||||
DBErrors LoadWallet(CWallet* pwallet);
|
DBErrors LoadWallet(CWallet* pwallet);
|
||||||
static bool Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys);
|
static bool Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys);
|
||||||
static bool Recover(CDBEnv& dbenv, std::string filename);
|
static bool Recover(CDBEnv& dbenv, std::string filename);
|
||||||
|
|
||||||
|
bool WriteWalletGenesisBlock(const CBlockLocator& locator)
|
||||||
|
{
|
||||||
|
nWalletDBUpdated++;
|
||||||
|
return Write(std::string("walletgenesisblock"), locator);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadWalletGenesisBlock(CBlockLocator& locator)
|
||||||
|
{
|
||||||
|
return Read(std::string("walletgenesisblock"), locator);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BITCOIN_WALLETDB_H
|
#endif // BITCOIN_WALLETDB_H
|
||||||
|
|||||||
@@ -1,36 +1,158 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include "walletserver.h"
|
#include "walletserver.h"
|
||||||
#include "main.h"
|
#include "walletserversession.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "bitcoinrpc.h"
|
#include "bitcoinrpc.h"
|
||||||
#include "ui_interface.h"
|
#include "wallet.h"
|
||||||
#include "stomp/booststomp.h"
|
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/uuid/uuid.hpp>
|
||||||
|
#include <boost/uuid/uuid_generators.hpp>
|
||||||
|
#include <boost/uuid/uuid_io.hpp>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/serialization/map.hpp>
|
#include <boost/serialization/map.hpp>
|
||||||
#include <boost/archive/binary_iarchive.hpp>
|
#include <boost/archive/binary_iarchive.hpp>
|
||||||
#include <boost/archive/binary_oarchive.hpp>
|
#include <boost/archive/binary_oarchive.hpp>
|
||||||
|
|
||||||
|
#include "json/json_spirit.h"
|
||||||
|
#include "json/json_spirit_writer_template.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
using namespace STOMP;
|
using namespace STOMP;
|
||||||
|
|
||||||
|
// Wallets Path
|
||||||
|
static boost::filesystem::path walletServerPath;
|
||||||
|
|
||||||
bool isServerRunning = false;
|
bool isServerRunning = false;
|
||||||
static BoostStomp* stomp_client;
|
|
||||||
// topics and queues
|
// in memory key/value store for sessions
|
||||||
static string block_notifications_topic = "/topic/Blocks";
|
static sessionKeyValueType sessions;
|
||||||
static string cmd_in_queue = "/queue/WalletCmdIn";
|
// in memory key/value store for session command queues
|
||||||
static string cmd_out_queue = "/queue/WalletCmdOut";
|
static sessionCommandQueueType sessionQueues;
|
||||||
// ActiveMQ parameters
|
// key string = accountId
|
||||||
static string stomp_host = GetArg("-activemqstomphost", "localhost");
|
//static std::map<std::string, WalletSession> walletSessions;
|
||||||
static int stomp_port = GetArg("activemqstompport", 61613);
|
// persisted key/value stores for wallets and server secrets
|
||||||
// in memory key/value stores
|
// key string = walletId / value string = accountId
|
||||||
typedef std::map<std::string, std::string> keyValueType;
|
static keyValueType wallets;
|
||||||
static keyValueType sessions;
|
// key string = walletId / value string = wallet server secret
|
||||||
static keyValueType walletServerSecrets;
|
static keyValueType walletServerSecrets;
|
||||||
|
|
||||||
|
// WalletServerSessions Thread Group
|
||||||
|
boost::thread_group walletServerSessionsTG;
|
||||||
|
|
||||||
|
std::string WalletServer::block_notifications_topic = std::string("/topic/Blocks");
|
||||||
|
std::string WalletServer::server_in_queue = "/queue/ServerInQueue";
|
||||||
|
std::string WalletServer::server_out_queue = "/queue/ServerOutQueue";
|
||||||
|
std::string WalletServer::stomp_host = GetArg("-activemqstomphost", "localhost");
|
||||||
|
int WalletServer::stomp_port = GetArg("activemqstompport", 61613);
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
WalletServer::WalletServer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartWalletServerThread()
|
||||||
|
{
|
||||||
|
// Make this thread recognisable as the wallet server thread
|
||||||
|
RenameThread("casinocoin-walletserver");
|
||||||
|
printf("CasinoCoin WalletServer Daemon starting\n");
|
||||||
|
// set server to running
|
||||||
|
isServerRunning = true;
|
||||||
|
// create the wallet directory if it not exists
|
||||||
|
walletServerPath = GetDataDir() / "wallets";
|
||||||
|
boost::filesystem::create_directories(walletServerPath);
|
||||||
|
printf("Using wallet directory: %s\n", walletServerPath.string().c_str());
|
||||||
|
// load wallet list and server secrets
|
||||||
|
walletServer.loadWalletServerSecrets();
|
||||||
|
walletServer.loadWalletList();
|
||||||
|
// initiate a new BoostStomp client
|
||||||
|
walletServer.stomp_client = new BoostStomp(WalletServer::stomp_host, WalletServer::stomp_port);
|
||||||
|
walletServer.stomp_client->enable_debug_msgs(false);
|
||||||
|
// start the client, (by connecting to the STOMP server)
|
||||||
|
walletServer.stomp_client->start();
|
||||||
|
// subscribe to server in queues
|
||||||
|
walletServer.stomp_client->subscribe(WalletServer::server_in_queue, (STOMP::pfnOnStompMessage_t) &walletServer.in_queue_callback);
|
||||||
|
// connect to NotifyStartNewWalletServerSession signal
|
||||||
|
walletServer.NotifyStartNewWalletServerSession.connect(boost::bind(&walletServer.NotifySessionCreated, &walletServer, _1, _2));
|
||||||
|
// connect to NotifyBlocksChanged signal
|
||||||
|
uiInterface.NotifyBlocksChanged.connect(boost::bind(&walletServer.NotifyBlocksChanged, &walletServer));
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopWalletServerThread()
|
||||||
|
{
|
||||||
|
if(isServerRunning)
|
||||||
|
{
|
||||||
|
// stop all wallet sessions
|
||||||
|
printf("StopWalletServerThread - Sending shutdown signal to all sessions\n");
|
||||||
|
for (sessionKeyValueType::iterator it=sessions.begin(); it!=sessions.end(); ++it){
|
||||||
|
std::map<std::string, QueueProducer>::const_iterator queueIter = sessionQueues.find(it->second.sessionId);
|
||||||
|
if(queueIter != sessionQueues.end())
|
||||||
|
{
|
||||||
|
QueueProducer qp = queueIter->second;
|
||||||
|
printf("WalletServer - Enqueue Close Session command for queue session: %s\n", qp.getSessionId().c_str());
|
||||||
|
Command cmd = {it->second.email, it->second.sessionId, "correlationId", "closesession"};
|
||||||
|
qp.Enqueue(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// remove sessions
|
||||||
|
sessions.clear();
|
||||||
|
// Interupt all WalletServerSession threads
|
||||||
|
printf("StopWalletServerThread - Session Threads: %i\n", walletServerSessionsTG.size());
|
||||||
|
printf("StopWalletServerThread - Interrupt All\n");
|
||||||
|
walletServerSessionsTG.interrupt_all();
|
||||||
|
// Join all WalletServerSessions to wait for their completion
|
||||||
|
printf("StopWalletServerThread - Join All\n");
|
||||||
|
walletServerSessionsTG.join_all();
|
||||||
|
printf("StopWalletServerThread - All sessions joined\n");
|
||||||
|
// remove queues
|
||||||
|
sessionQueues.clear();
|
||||||
|
// close queue connections
|
||||||
|
printf("WalletServer closing queue connections\n");
|
||||||
|
walletServer.stomp_client->stop();
|
||||||
|
delete walletServer.stomp_client;
|
||||||
|
// save wallet list and server secrets to file
|
||||||
|
walletServer.saveWalletList();
|
||||||
|
walletServer.saveWalletServerSecrets();
|
||||||
|
// stop server thread
|
||||||
|
isServerRunning = false;
|
||||||
|
printf("WalletServer STOPPED\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flushWalletsThread()
|
||||||
|
{
|
||||||
|
printf("WalletServer - flushWalletsThread");
|
||||||
|
// TRY_LOCK(bitdb.cs_db,lockDb);
|
||||||
|
// if (lockDb)
|
||||||
|
// {
|
||||||
|
// // Don't do this if any databases are in use
|
||||||
|
// int nRefCount = 0;
|
||||||
|
// map<string, int>::iterator mi = bitdb.mapFileUseCount.begin();
|
||||||
|
// while (mi != bitdb.mapFileUseCount.end())
|
||||||
|
// {
|
||||||
|
// nRefCount += (*mi).second;
|
||||||
|
// mi++;
|
||||||
|
// }
|
||||||
|
// if (nRefCount == 0)
|
||||||
|
// {
|
||||||
|
// boost::this_thread::interruption_point();
|
||||||
|
// map<string, int>::iterator mi = bitdb.mapFileUseCount.find(clientWallet->strWalletFile);
|
||||||
|
// if (mi != bitdb.mapFileUseCount.end())
|
||||||
|
// {
|
||||||
|
// int64 nStart = GetTimeMillis();
|
||||||
|
// // Flush wallet.dat so it's self contained
|
||||||
|
// bitdb.CloseDb(clientWallet->strWalletFile);
|
||||||
|
// bitdb.CheckpointLSN(clientWallet->strWalletFile);
|
||||||
|
// bitdb.mapFileUseCount.erase(mi++);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// printf("WalletServerSession - Could not get lock to execute Flush for session %s\n",sessionId.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// Handler for NotifyBlocksChanged signal
|
// Handler for NotifyBlocksChanged signal
|
||||||
static void NotifyBlocksChanged()
|
void WalletServer::NotifyBlocksChanged()
|
||||||
{
|
{
|
||||||
printf("CasinoCoin WalletServer Received NotifyBlocksChanged Signal: %i BlockHash: %s\n", nBestHeight, hashBestChain.ToString().c_str());
|
printf("CasinoCoin WalletServer Received NotifyBlocksChanged Signal: %i BlockHash: %s\n", nBestHeight, hashBestChain.ToString().c_str());
|
||||||
// get the block from the database
|
// get the block from the database
|
||||||
@@ -42,108 +164,453 @@ static void NotifyBlocksChanged()
|
|||||||
try {
|
try {
|
||||||
// construct a headermap
|
// construct a headermap
|
||||||
STOMP::hdrmap headers;
|
STOMP::hdrmap headers;
|
||||||
headers["content-type"] = string("application/json");
|
headers["Content-Type"] = string("application/json");
|
||||||
string body = json_spirit::write_string(jsonBlock, false);
|
string body = json_spirit::write_string(jsonBlock, false);
|
||||||
// add an outgoing message to the topic
|
// add an outgoing message to the topic
|
||||||
stomp_client->send(block_notifications_topic, headers, body);
|
walletServer.stomp_client->send(WalletServer::block_notifications_topic, headers, body);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
cerr << "Error in BoostStomp: " << e.what() << "\n";
|
cerr << "Error in BoostStomp: " << e.what() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler for NotifySessionCreated signal
|
// Handler for incomming queue messages
|
||||||
static void NotifySessionCreated(std::string accountId, std::string sessionId)
|
bool WalletServer::in_queue_callback(STOMP::Frame& _frame)
|
||||||
{
|
{
|
||||||
sessions.insert(std::make_pair(accountId, sessionId));
|
std::string jsonBody = std::string(_frame.body().c_str());
|
||||||
cout << "Inserted: " << accountId.c_str() << " / " << sessionId.c_str() << endl;
|
json_spirit::mValue jsonValue;
|
||||||
}
|
json_spirit::read_string(jsonBody, jsonValue);
|
||||||
|
json_spirit::mObject jsonObject = jsonValue.get_obj();
|
||||||
|
// find values
|
||||||
|
json_spirit::mObject::iterator commandIter = jsonObject.find("command");
|
||||||
|
json_spirit::mObject::iterator sessionIter = jsonObject.find("sessionid");
|
||||||
|
json_spirit::mObject::iterator accountIter = jsonObject.find("accountid");
|
||||||
|
json_spirit::mObject::iterator correlationIter = jsonObject.find("correlationid");
|
||||||
|
if(commandIter != jsonObject.end() &&
|
||||||
|
sessionIter != jsonObject.end() &&
|
||||||
|
accountIter != jsonObject.end() &&
|
||||||
|
correlationIter != jsonObject.end())
|
||||||
|
{
|
||||||
|
std::string command = commandIter->second.get_str();
|
||||||
|
std::string sessionId = sessionIter->second.get_str();
|
||||||
|
std::string accountId = accountIter->second.get_str();
|
||||||
|
std::string correlationId = correlationIter->second.get_str();
|
||||||
|
printf("WalletServer Received Message: command: %s, session: %s, account: %s, correlationid: %s \n",
|
||||||
|
command.c_str(), sessionId.c_str(), accountId.c_str(), correlationId.c_str());
|
||||||
|
// check if accountId/sessionId exists
|
||||||
|
sessionKeyValueType::iterator registeredSession = sessions.find(accountId);
|
||||||
|
if(registeredSession != sessions.end())
|
||||||
|
{
|
||||||
|
Session msgSession = registeredSession->second;
|
||||||
|
if(msgSession.sessionId.compare(sessionId) == 0)
|
||||||
|
{
|
||||||
|
if(command.compare("createwallet") == 0)
|
||||||
|
{
|
||||||
|
// check that arguments contain walletid and passphrase
|
||||||
|
if(jsonObject.find("arguments") != jsonObject.end())
|
||||||
|
{
|
||||||
|
json_spirit::mObject argumentsObject = jsonObject.find("arguments")->second.get_obj();
|
||||||
|
if (argumentsObject.find("passphrase") != argumentsObject.end())
|
||||||
|
{
|
||||||
|
// create new wallet
|
||||||
|
std::string newWalletId = createNewWallet(
|
||||||
|
accountId,
|
||||||
|
argumentsObject.find("passphrase")->second.get_str()
|
||||||
|
);
|
||||||
|
printf("WalletServer created new wallet with id: %s\n", newWalletId.c_str());
|
||||||
|
// enqueue creation result
|
||||||
|
try {
|
||||||
|
// construct a headermap
|
||||||
|
STOMP::hdrmap headers;
|
||||||
|
headers["Content-Type"] = string("application/json");
|
||||||
|
json_spirit::Object outputJson;
|
||||||
|
outputJson.push_back(json_spirit::Pair("sessionid", sessionId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("correlationid", correlationId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("command", command));
|
||||||
|
json_spirit::Object result;
|
||||||
|
result.push_back(json_spirit::Pair("errorCode", 0));
|
||||||
|
result.push_back(json_spirit::Pair("errorMessage", ""));
|
||||||
|
result.push_back(json_spirit::Pair("walletid", newWalletId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("result", result));
|
||||||
|
// add an outgoing message to the topic
|
||||||
|
std::string body = json_spirit::write(outputJson);
|
||||||
|
printf("WalletServer JSON: %s\n", body.c_str());
|
||||||
|
walletServer.stomp_client->send(WalletServer::server_out_queue, headers, body);
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
cerr << "Error in BoostStomp: " << e.what() << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sendErrorMessage(104, sessionId, correlationId, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// all other commands will be send to the WalletServerSessions
|
||||||
|
//
|
||||||
|
// Get the arguments object
|
||||||
|
if(jsonObject.find("arguments") != jsonObject.end())
|
||||||
|
{
|
||||||
|
json_spirit::mObject argumentsObject = jsonObject.find("arguments")->second.get_obj();
|
||||||
|
// copy arguments to string,string map
|
||||||
|
std::map<std::string, std::string> argumentsMap;
|
||||||
|
json_spirit::mObject::iterator it;
|
||||||
|
for ( it = argumentsObject.begin(); it != argumentsObject.end(); it++ )
|
||||||
|
{
|
||||||
|
argumentsMap.insert(std::make_pair(it->first, it->second.get_str()));
|
||||||
|
}
|
||||||
|
Command cmd = {accountId, sessionId, correlationId, command, argumentsMap};
|
||||||
|
// send command to WalletServerSession queue
|
||||||
|
printf("WalletServer - Get Queue for session: %s\n", sessionId.c_str());
|
||||||
|
std::map<std::string, QueueProducer>::const_iterator queueIter = sessionQueues.find(sessionId);
|
||||||
|
if(queueIter != sessionQueues.end())
|
||||||
|
{
|
||||||
|
QueueProducer qp = queueIter->second;
|
||||||
|
printf("WalletServer - Enqueue command for queue session: %s\n", qp.getSessionId().c_str());
|
||||||
|
qp.Enqueue(cmd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("WalletServer - Queue not found for session: %s\n", sessionId.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Construct and send error message
|
||||||
|
sendErrorMessage(100, sessionId, correlationId, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sendErrorMessage(105, sessionId, correlationId, command);
|
||||||
|
|
||||||
// load wallet server secret map from filesystem
|
}
|
||||||
void loadWalletServerSecrets()
|
else
|
||||||
{
|
sendErrorMessage(106, sessionId, correlationId, command);
|
||||||
boost::filesystem::path walletServerMapPath = GetDataDir() / "walletserver.dat";
|
}
|
||||||
std::ifstream ifs(walletServerMapPath.string().c_str());
|
else
|
||||||
boost::archive::binary_iarchive bia(ifs);
|
printf("WalletServer could not parse message. Either SessionId, AccountId, CorrelationId or Command is missing");
|
||||||
bia >> walletServerSecrets;
|
// processing complete
|
||||||
}
|
|
||||||
|
|
||||||
// save wallet server secret map to filesystem
|
|
||||||
void saveWalletServerSecrets()
|
|
||||||
{
|
|
||||||
boost::filesystem::path walletServerMapPath = GetDataDir() / "walletserver.dat";
|
|
||||||
std::ofstream ofs(walletServerMapPath.string().c_str());
|
|
||||||
boost::archive::binary_oarchive boa(ofs);
|
|
||||||
boa << walletServerSecrets;
|
|
||||||
}
|
|
||||||
|
|
||||||
//bool session_callback(STOMP::Frame& _frame) {
|
|
||||||
// cout << "--Incoming STOMP Frame--" << endl;
|
|
||||||
// cout << " Headers:" << endl;
|
|
||||||
// hdrmap headers = _frame.headers();
|
|
||||||
// for (STOMP::hdrmap::iterator it = headers.begin() ; it != headers.end(); it++ )
|
|
||||||
// cout << "\t" << (*it).first << "\t=>\t" << (*it).second << endl;
|
|
||||||
// //
|
|
||||||
// cout << " Body: (size: " << _frame.body().v.size() << " chars):" << endl;
|
|
||||||
// hexdump(_frame.body().c_str(), _frame.body().v.size() );
|
|
||||||
// return(true); // return false if we want to disacknowledge the frame (send NACK instead of ACK)
|
|
||||||
//}
|
|
||||||
|
|
||||||
bool in_queue_callback(STOMP::Frame& _frame) {
|
|
||||||
cout << "--Incoming STOMP Frame--" << endl;
|
|
||||||
cout << " Headers:" << endl;
|
|
||||||
hdrmap headers = _frame.headers();
|
|
||||||
for (STOMP::hdrmap::iterator it = headers.begin() ; it != headers.end(); it++ )
|
|
||||||
cout << "\t" << (*it).first << "\t=>\t" << (*it).second << endl;
|
|
||||||
//
|
|
||||||
cout << " Body: (size: " << _frame.body().v.size() << " chars):" << endl;
|
|
||||||
hexdump(_frame.body().c_str(), _frame.body().v.size() );
|
|
||||||
return(true); // return false if we want to disacknowledge the frame (send NACK instead of ACK)
|
return(true); // return false if we want to disacknowledge the frame (send NACK instead of ACK)
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartWalletServerThread()
|
bool WalletServer::out_queue_callback(STOMP::Frame& _frame)
|
||||||
{
|
{
|
||||||
// Make this thread recognisable as the wallet server thread
|
printf("out_queue_callback: %s", _frame.body().c_str());
|
||||||
RenameThread("casinocoin-walletserver");
|
return(true); // return false if we want to disacknowledge the frame (send NACK instead of ACK)
|
||||||
printf("CasinoCoin WalletServer Daemon starting\n");
|
|
||||||
// get the wallet dir
|
|
||||||
boost::filesystem::path walletServerPath = GetDataDir() / "wallets";
|
|
||||||
boost::filesystem::create_directories(walletServerPath);
|
|
||||||
printf("Using wallet directory: %s\n", walletServerPath.string().c_str());
|
|
||||||
// initiate a new BoostStomp client
|
|
||||||
stomp_client = new BoostStomp(stomp_host, stomp_port);
|
|
||||||
// start the client, (by connecting to the STOMP server)
|
|
||||||
stomp_client->start();
|
|
||||||
// subscribe to the In Queue to receive the incomming commands
|
|
||||||
stomp_client->subscribe(cmd_in_queue, (STOMP::pfnOnStompMessage_t) &in_queue_callback);
|
|
||||||
isServerRunning = true;
|
|
||||||
// connect to NotifyStartNewWalletServerSession signal
|
|
||||||
uiInterface.NotifyStartNewWalletServerSession.connect(boost::bind(NotifySessionCreated, _1, _2));
|
|
||||||
// connect to NotifyBlocksChanged signal
|
|
||||||
uiInterface.NotifyBlocksChanged.connect(boost::bind(NotifyBlocksChanged));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StopWalletServerThread()
|
// Handler for NotifySessionCreated signal
|
||||||
|
void WalletServer::NotifySessionCreated(std::string accountId, Session session)
|
||||||
{
|
{
|
||||||
if(isServerRunning)
|
// save session in memory
|
||||||
|
sessions.insert(std::make_pair(accountId, session));
|
||||||
|
Session &newSession = sessions.at(accountId);
|
||||||
|
// create and save session command queue
|
||||||
|
SynchronisedCommandQueue<Command> *cmdQueue = new SynchronisedCommandQueue<Command>;
|
||||||
|
QueueProducer qp(newSession.sessionId, cmdQueue);
|
||||||
|
sessionQueues.insert(std::make_pair(newSession.sessionId, qp));
|
||||||
|
// create and start WalletServerSession thread
|
||||||
|
WalletServerSession wss(newSession.sessionId, cmdQueue);
|
||||||
|
walletServerSessionsTG.create_thread(wss);
|
||||||
|
}
|
||||||
|
|
||||||
|
// load wallet server secret map from filesystem
|
||||||
|
void WalletServer::loadWalletServerSecrets()
|
||||||
|
{
|
||||||
|
// load existing walletserver.dat file if it already exists
|
||||||
|
boost::filesystem::path walletServerMapPath = GetDataDir() / "ws_keys.dat";
|
||||||
|
if(boost::filesystem::exists(walletServerMapPath))
|
||||||
{
|
{
|
||||||
// unsubscribe from In Queue
|
std::ifstream ifs(walletServerMapPath.string().c_str());
|
||||||
stomp_client->unsubscribe(cmd_in_queue);
|
boost::archive::binary_iarchive bia(ifs);
|
||||||
// flush all Server Wallets
|
bia >> walletServerSecrets;
|
||||||
printf("WalletServer flushing wallets\n");
|
|
||||||
// close queue connections
|
|
||||||
printf("WalletServer closing queue connections\n");
|
|
||||||
stomp_client->stop();
|
|
||||||
delete stomp_client;
|
|
||||||
// stop server thread
|
|
||||||
isServerRunning = false;
|
|
||||||
printf("WalletServer STOPPED\n");
|
|
||||||
}
|
}
|
||||||
|
printf("CasinoCoin WalletServer: %i walletsecrets loaded\n", walletServerSecrets.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNewAccountId(std::string accountId){
|
// save wallet server secret map to filesystem
|
||||||
|
void WalletServer::saveWalletServerSecrets()
|
||||||
|
{
|
||||||
|
boost::filesystem::path walletServerMapPath = GetDataDir() / "ws_keys.dat";
|
||||||
|
std::ofstream ofs(walletServerMapPath.string().c_str());
|
||||||
|
boost::archive::binary_oarchive boa(ofs);
|
||||||
|
boa << walletServerSecrets;
|
||||||
|
printf("CasinoCoin WalletServer: %i walletsecrets saved\n", walletServerSecrets.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// load wallet list map from filesystem
|
||||||
|
void WalletServer::loadWalletList()
|
||||||
|
{
|
||||||
|
// load existing walletlist.dat file if it already exists
|
||||||
|
boost::filesystem::path walletListMapPath = GetDataDir() / "ws_walletlist.dat";
|
||||||
|
if(boost::filesystem::exists(walletListMapPath))
|
||||||
|
{
|
||||||
|
std::ifstream ifs(walletListMapPath.string().c_str());
|
||||||
|
boost::archive::binary_iarchive bia(ifs);
|
||||||
|
bia >> wallets;
|
||||||
|
}
|
||||||
|
printf("CasinoCoin WalletServer: %i wallets loaded\n", wallets.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// save wallet list map to filesystem
|
||||||
|
void WalletServer::saveWalletList()
|
||||||
|
{
|
||||||
|
boost::filesystem::path walletListMapPath = GetDataDir() / "ws_walletlist.dat";
|
||||||
|
std::ofstream ofs(walletListMapPath.string().c_str());
|
||||||
|
boost::archive::binary_oarchive boa(ofs);
|
||||||
|
boa << wallets;
|
||||||
|
printf("CasinoCoin WalletServer: %i wallets saved\n", wallets.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WalletServer::isNewAccountId(std::string accountId)
|
||||||
|
{
|
||||||
return (sessions.count(accountId) == 0);
|
return (sessions.count(accountId) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sessionKeyValueType& WalletServer::getSessions()
|
||||||
|
{
|
||||||
|
return sessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
Session& WalletServer::getSession(std::string sessionId)
|
||||||
|
{
|
||||||
|
// loop over sessions to find the session with its session id
|
||||||
|
BOOST_FOREACH(sessionKeyValueType::value_type &session, sessions)
|
||||||
|
{
|
||||||
|
if(session.second.sessionId.compare(sessionId) == 0)
|
||||||
|
{
|
||||||
|
return session.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Not found so define default output object
|
||||||
|
Session s = {"","",0,false,0};
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyValueType WalletServer::getWallets()
|
||||||
|
{
|
||||||
|
return wallets;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WalletServer::deleteSession(std::string sessionId)
|
||||||
|
{
|
||||||
|
// loop over sessions to find the session with its session id
|
||||||
|
BOOST_FOREACH(sessionKeyValueType::value_type &session, sessions)
|
||||||
|
{
|
||||||
|
if(session.second.sessionId.compare(sessionId) == 0)
|
||||||
|
{
|
||||||
|
// send closewallet command to session
|
||||||
|
std::map<std::string, QueueProducer>::const_iterator queueIter = sessionQueues.find(session.second.sessionId);
|
||||||
|
if(queueIter != sessionQueues.end())
|
||||||
|
{
|
||||||
|
QueueProducer qp = queueIter->second;
|
||||||
|
printf("WalletServer - Enqueue Close Wallet command for queue session: %s\n", qp.getSessionId().c_str());
|
||||||
|
Command cmd = {session.second.email, session.second.sessionId, "correlationId", "closewallet"};
|
||||||
|
qp.Enqueue(cmd);
|
||||||
|
}
|
||||||
|
// remove sessions object
|
||||||
|
sessions.erase(session.first);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string WalletServer::createNewWallet(std::string accountId, std::string passphrase)
|
||||||
|
{
|
||||||
|
printf("WalletServer Create new wallet for accout id: %s\n", accountId.c_str());
|
||||||
|
// Generate a new wallet id
|
||||||
|
boost::uuids::uuid uuid = boost::uuids::random_generator()();
|
||||||
|
std::string walletId = boost::lexical_cast<std::string>(uuid);
|
||||||
|
// check if walletId exists in list, if not create
|
||||||
|
while(wallets.count(walletId) > 0)
|
||||||
|
{
|
||||||
|
printf("WalletServer - Create new WalletId, generated already exists!\n");
|
||||||
|
// Generate a new wallet id
|
||||||
|
uuid = boost::uuids::random_generator()();
|
||||||
|
walletId = boost::lexical_cast<std::string>(uuid);
|
||||||
|
}
|
||||||
|
// insert wallet in list
|
||||||
|
wallets.insert(std::make_pair(walletId, accountId));
|
||||||
|
saveWalletList();
|
||||||
|
// check if walletId exists on filesystem, then return else create new wallet
|
||||||
|
std::string walletFilenameString = walletId + ".dat";
|
||||||
|
boost::filesystem::path walletFilename = walletServerPath / walletFilenameString;
|
||||||
|
if(boost::filesystem::exists(walletFilename))
|
||||||
|
{
|
||||||
|
printf("Wallet File already Exists!: %s\n", walletFilename.string().c_str());
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Create Wallet File with name: %s\n", walletFilename.string().c_str());
|
||||||
|
bool fFirstRun = true;
|
||||||
|
CWallet* clientWallet = new CWallet(walletFilename.string());
|
||||||
|
DBErrors nLoadWalletRet = clientWallet->LoadWallet(fFirstRun);
|
||||||
|
std::ostringstream strLoadResult;
|
||||||
|
if (nLoadWalletRet != DB_LOAD_OK)
|
||||||
|
{
|
||||||
|
if (nLoadWalletRet == DB_CORRUPT)
|
||||||
|
strLoadResult << _("Error loading wallet file: Wallet corrupted") << "\n";
|
||||||
|
else if (nLoadWalletRet == DB_NONCRITICAL_ERROR)
|
||||||
|
{
|
||||||
|
printf("Warning: error reading wallet file! All keys read correctly, but transaction data"
|
||||||
|
" or address book entries might be missing or incorrect.");
|
||||||
|
}
|
||||||
|
else if (nLoadWalletRet == DB_TOO_NEW)
|
||||||
|
strLoadResult << _("Error loading wallet file: Wallet requires newer version of CasinoCoin") << "\n";
|
||||||
|
else if (nLoadWalletRet == DB_NEED_REWRITE)
|
||||||
|
{
|
||||||
|
strLoadResult << _("Wallet needed to be rewritten: restart CasinoCoin to complete") << "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strLoadResult << _("Error loading wallet.dat") << "\n";
|
||||||
|
// load wallet result
|
||||||
|
printf("Load Wallet result: %s", strLoadResult.str().c_str());
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strLoadResult << "Wallet file succesfully loaded, Firstrun?: " << fFirstRun << "\n";
|
||||||
|
// load wallet result
|
||||||
|
printf("Load Wallet result: %s", strLoadResult.str().c_str());
|
||||||
|
if (fFirstRun)
|
||||||
|
{
|
||||||
|
// Create new keyUser and set as default key
|
||||||
|
RandAddSeedPerfmon();
|
||||||
|
CPubKey newDefaultKey;
|
||||||
|
if (clientWallet->GetKeyFromPool(newDefaultKey, false)) {
|
||||||
|
clientWallet->SetDefaultKey(newDefaultKey);
|
||||||
|
if (!clientWallet->SetAddressBookName(clientWallet->vchDefaultKey.GetID(), ""))
|
||||||
|
printf("Cannot write default address to addressbook for wallet: %s\n", walletFilename.string().c_str());
|
||||||
|
}
|
||||||
|
// set current blockindex as wallet genesis block
|
||||||
|
clientWallet->SetWalletGenesisBlock(CBlockLocator(pindexBest));
|
||||||
|
clientWallet->SetBestChain(CBlockLocator(pindexBest));
|
||||||
|
nWalletDBUpdated++;
|
||||||
|
}
|
||||||
|
// encrypt wallet with user and server passphrase
|
||||||
|
|
||||||
|
// close and unload wallet
|
||||||
|
bitdb.CloseDb(walletFilename.string());
|
||||||
|
}
|
||||||
|
return walletId;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
printf("%s", strErrors.str().c_str());
|
||||||
|
printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
|
||||||
|
|
||||||
|
RegisterWallet(pwalletMain);
|
||||||
|
|
||||||
|
CBlockIndex *pindexRescan = pindexBest;
|
||||||
|
if (GetBoolArg("-rescan"))
|
||||||
|
pindexRescan = pindexGenesisBlock;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CWalletDB walletdb("wallet.dat");
|
||||||
|
CBlockLocator locator;
|
||||||
|
if (walletdb.ReadBestBlock(locator))
|
||||||
|
pindexRescan = locator.GetBlockIndex();
|
||||||
|
else
|
||||||
|
pindexRescan = pindexGenesisBlock;
|
||||||
|
}
|
||||||
|
if (pindexBest && pindexBest != pindexRescan)
|
||||||
|
{
|
||||||
|
uiInterface.InitMessage(_("Rescanning..."));
|
||||||
|
printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight);
|
||||||
|
nStart = GetTimeMillis();
|
||||||
|
pwalletMain->ScanForWalletTransactions(pindexRescan, true);
|
||||||
|
printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
|
||||||
|
pwalletMain->SetBestChain(CBlockLocator(pindexBest));
|
||||||
|
nWalletDBUpdated++;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WalletServer::isWalletAccountValid(std::string walletId, std::string accountId)
|
||||||
|
{
|
||||||
|
keyValueType::iterator wallet = wallets.find(walletId);
|
||||||
|
if(wallet != wallets.end())
|
||||||
|
{
|
||||||
|
std::string listAccountId = wallet->second;
|
||||||
|
if(listAccountId.compare(accountId) == 0)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::filesystem::path WalletServer::getWalletServerPath()
|
||||||
|
{
|
||||||
|
return walletServerPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send json error message to out queue
|
||||||
|
void WalletServer::sendErrorMessage(int errorCode, std::string sessionId, std::string correlationId, std::string command)
|
||||||
|
{
|
||||||
|
// Construct and send error message
|
||||||
|
STOMP::hdrmap headers;
|
||||||
|
headers["Content-Type"] = string("application/json");
|
||||||
|
json_spirit::Object outputJson;
|
||||||
|
outputJson.push_back(json_spirit::Pair("sessionid", sessionId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("correlationid", correlationId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("command", command));
|
||||||
|
json_spirit::Object result;
|
||||||
|
result.push_back(json_spirit::Pair("errorCode", errorCode));
|
||||||
|
// define error messages
|
||||||
|
std::string errorMessage = "There was an error executing command " + command;
|
||||||
|
if(errorCode == 10)
|
||||||
|
errorMessage = "There was an error executing command '" + command + "'";
|
||||||
|
else if(errorCode == 100)
|
||||||
|
errorMessage = "No arguments supplied for WalletServer command " + command;
|
||||||
|
else if(errorCode == 101)
|
||||||
|
errorMessage = "No Wallet ID supplied in arguments array.";
|
||||||
|
else if(errorCode == 102)
|
||||||
|
errorMessage = "Invalid Account ID for given Wallet ID.";
|
||||||
|
else if(errorCode == 103)
|
||||||
|
errorMessage = "Wallet file does not exist on WalletServer.";
|
||||||
|
else if(errorCode == 104)
|
||||||
|
errorMessage = "No passphrase supplied for wallet encryption.";
|
||||||
|
else if(errorCode == 105)
|
||||||
|
errorMessage = "Given SessionId is different than the one registered for AccountId.";
|
||||||
|
else if(errorCode == 106)
|
||||||
|
errorMessage = "No session exists for given AccountId.";
|
||||||
|
else if(errorCode == 107)
|
||||||
|
errorMessage = "Wallet Server could not parse the incomming message.";
|
||||||
|
else if(errorCode == 108)
|
||||||
|
errorMessage = "Wallet is already open.";
|
||||||
|
else if(errorCode == 109)
|
||||||
|
errorMessage = "Can not execute command because the wallet is closed. Please open the wallet before executing commands on it.";
|
||||||
|
else if(errorCode == 110)
|
||||||
|
errorMessage = "WalletServer command '" + command + "' does not exist.";
|
||||||
|
else if(errorCode == 111)
|
||||||
|
errorMessage = "Invalid CasinoCoin address.";
|
||||||
|
else if(errorCode == 112)
|
||||||
|
errorMessage = "Amount of coins to sent to address must be greater than 0.";
|
||||||
|
// create output JSON
|
||||||
|
result.push_back(json_spirit::Pair("errorMessage", errorMessage));
|
||||||
|
outputJson.push_back(json_spirit::Pair("result", result));
|
||||||
|
// add an outgoing message to the topic
|
||||||
|
std::string body = json_spirit::write(outputJson);
|
||||||
|
printf("WalletServer JSON: %s\n", body.c_str());
|
||||||
|
walletServer.stomp_client->send(WalletServer::server_out_queue, headers, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletServer::setLastCommandTime(std::string sessionId, int newTime)
|
||||||
|
{
|
||||||
|
getSession(sessionId).lastCommandTime = newTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletServer::setWalletOpen(std::string sessionId, bool newStatus)
|
||||||
|
{
|
||||||
|
getSession(sessionId).walletOpen = newStatus;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,13 +1,163 @@
|
|||||||
#ifndef WALLETSERVER_H
|
#ifndef WALLETSERVER_H
|
||||||
#define WALLETSERVER_H
|
#define WALLETSERVER_H
|
||||||
|
|
||||||
#include <boost/signals2/signal.hpp>
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <queue>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/signals2.hpp>
|
||||||
|
#include <boost/thread/mutex.hpp>
|
||||||
|
#include <boost/thread/condition_variable.hpp>
|
||||||
|
#include <boost/thread/locks.hpp>
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
#include "stomp/booststomp.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
struct Session {
|
||||||
|
std::string email;
|
||||||
|
std::string sessionId;
|
||||||
|
int creationTime;
|
||||||
|
bool walletOpen;
|
||||||
|
int lastCommandTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Command {
|
||||||
|
std::string accountId;
|
||||||
|
std::string sessionId;
|
||||||
|
std::string correlationId;
|
||||||
|
std::string command;
|
||||||
|
std::map<std::string, std::string> arguments;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Queue class that has thread synchronisation
|
||||||
|
template <typename T> class SynchronisedCommandQueue
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::queue<T> m_queue; // Use STL queue to store data
|
||||||
|
boost::mutex m_mutex; // The mutex to synchronise on
|
||||||
|
boost::condition_variable m_cond; // The condition to wait for
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Add data to the queue and notify others
|
||||||
|
void Enqueue(const T& data)
|
||||||
|
{
|
||||||
|
// Acquire lock on the queue
|
||||||
|
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||||
|
// Add the data to the queue
|
||||||
|
m_queue.push(data);
|
||||||
|
// Notify others that data is ready
|
||||||
|
m_cond.notify_one();
|
||||||
|
} // Lock is automatically released here
|
||||||
|
|
||||||
|
// Get data from the queue. Wait for data if not available
|
||||||
|
T Dequeue()
|
||||||
|
{
|
||||||
|
// Acquire lock on the queue
|
||||||
|
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||||
|
// When there is no data, wait till someone fills it.
|
||||||
|
// Lock is automatically released in the wait and obtained
|
||||||
|
// again after the wait
|
||||||
|
while (m_queue.size()==0)
|
||||||
|
m_cond.wait(lock);
|
||||||
|
// Retrieve the data from the queue
|
||||||
|
T result = m_queue.front();
|
||||||
|
m_queue.pop();
|
||||||
|
return result;
|
||||||
|
} // Lock is automatically released here
|
||||||
|
};
|
||||||
|
|
||||||
|
class QueueProducer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::string m_session_id; // The id of the session
|
||||||
|
SynchronisedCommandQueue<Command>* m_queue; // The queue to use
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructor with id and the queue to use
|
||||||
|
QueueProducer(std::string sessionId, SynchronisedCommandQueue<Command>* queue)
|
||||||
|
{
|
||||||
|
m_session_id = sessionId;
|
||||||
|
m_queue=queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator () ()
|
||||||
|
{
|
||||||
|
// keep running until interupted
|
||||||
|
while(true)
|
||||||
|
boost::this_thread::interruption_point();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The thread function fills the queue with data
|
||||||
|
void Enqueue(Command data)
|
||||||
|
{
|
||||||
|
m_queue->Enqueue(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getSessionId()
|
||||||
|
{
|
||||||
|
return m_session_id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<std::string, Session> sessionKeyValueType;
|
||||||
|
typedef std::map<std::string, QueueProducer> sessionCommandQueueType;
|
||||||
|
typedef std::map<std::string, std::string> keyValueType;
|
||||||
|
|
||||||
extern bool isServerRunning;
|
extern bool isServerRunning;
|
||||||
|
|
||||||
|
// Server Start/Stop/Flush methods
|
||||||
void StartWalletServerThread();
|
void StartWalletServerThread();
|
||||||
void StopWalletServerThread();
|
void StopWalletServerThread();
|
||||||
|
|
||||||
bool isNewAccountId(std::string accountId);
|
// Class that cointains all WalletServer commands
|
||||||
|
class WalletServer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
WalletServer();
|
||||||
|
|
||||||
|
// WalletServer Signals
|
||||||
|
boost::signals2::signal<void (std::string accountId, Session session)> NotifyStartNewWalletServerSession;
|
||||||
|
boost::signals2::signal<void (std::string sessionId)> SessionShutdownSignal;
|
||||||
|
|
||||||
|
// topics and queues
|
||||||
|
static std::string block_notifications_topic;
|
||||||
|
static std::string server_in_queue;
|
||||||
|
static std::string server_out_queue;
|
||||||
|
// ActiveMQ parameters
|
||||||
|
static std::string stomp_host;
|
||||||
|
static int stomp_port;
|
||||||
|
// STOMP Client
|
||||||
|
STOMP::BoostStomp* stomp_client;
|
||||||
|
// WalletServer genesisblock
|
||||||
|
static CBlockIndex wsGenesisBlock;
|
||||||
|
|
||||||
|
// list persistance methods
|
||||||
|
void loadWalletServerSecrets();
|
||||||
|
void saveWalletServerSecrets();
|
||||||
|
void loadWalletList();
|
||||||
|
void saveWalletList();
|
||||||
|
|
||||||
|
// wallet commands
|
||||||
|
bool isNewAccountId(std::string accountId);
|
||||||
|
sessionKeyValueType& getSessions();
|
||||||
|
Session& getSession(std::string sessionId);
|
||||||
|
bool deleteSession(std::string sessionId);
|
||||||
|
std::string createNewWallet(std::string accountId, std::string passphrase);
|
||||||
|
keyValueType getWallets();
|
||||||
|
bool isWalletAccountValid(std::string walletId, std::string accountId);
|
||||||
|
boost::filesystem::path getWalletServerPath();
|
||||||
|
void setLastCommandTime(std::string sessionId, int newTime);
|
||||||
|
void setWalletOpen(std::string sessionId, bool newStatus);
|
||||||
|
|
||||||
|
void sendErrorMessage(int errorCode, std::string sessionId, std::string correlationId, std::string command);
|
||||||
|
bool in_queue_callback(STOMP::Frame& _frame);
|
||||||
|
bool out_queue_callback(STOMP::Frame& _frame);
|
||||||
|
void NotifyBlocksChanged();
|
||||||
|
void NotifySessionCreated(std::string accountId, Session session);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
extern WalletServer walletServer;
|
||||||
|
|
||||||
#endif // WALLETSERVER_H
|
#endif // WALLETSERVER_H
|
||||||
|
|||||||
504
src/walletserversession.cpp
Normal file
504
src/walletserversession.cpp
Normal file
@@ -0,0 +1,504 @@
|
|||||||
|
#include "walletserversession.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "bitcoinrpc.h"
|
||||||
|
#include "json/json_spirit.h"
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
WalletServerSession::WalletServerSession(std::string newSessionId, SynchronisedCommandQueue<Command>* queue)
|
||||||
|
{
|
||||||
|
sessionId = newSessionId;
|
||||||
|
m_queue = queue;
|
||||||
|
walletOpen = false;
|
||||||
|
walletServer.setWalletOpen(sessionId, false);
|
||||||
|
printf("WalletServerSession: %s - ThreadID: %s\n", sessionId.c_str(), boost::lexical_cast<std::string>(boost::this_thread::get_id()).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
WalletServerSession::~WalletServerSession()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletServerSession::NotifyBlocksChanged()
|
||||||
|
{
|
||||||
|
if(walletOpen)
|
||||||
|
{
|
||||||
|
// load the new block from disk
|
||||||
|
CBlock block;
|
||||||
|
CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
|
||||||
|
block.ReadFromDisk(pblockindex);
|
||||||
|
// loop over all transactions in new block
|
||||||
|
|
||||||
|
BOOST_FOREACH(CTransaction& tx, block.vtx)
|
||||||
|
{
|
||||||
|
clientWallet->AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, true);
|
||||||
|
}
|
||||||
|
// update block height
|
||||||
|
LOCK(clientWallet->cs_wallet);
|
||||||
|
clientWallet->SetBestChain(CBlockLocator(pblockindex));
|
||||||
|
nWalletDBUpdated++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletServerSession::NotifyTransactionChanged(CWallet *wallet, const uint256 &hash, ChangeType status)
|
||||||
|
{
|
||||||
|
if(walletOpen && status == CT_NEW)
|
||||||
|
{
|
||||||
|
CWalletTx tx;
|
||||||
|
clientWallet->GetTransaction(hash, tx);
|
||||||
|
int64 nFee;
|
||||||
|
std::string strSentAccount;
|
||||||
|
list<pair<CTxDestination, int64> > listReceived;
|
||||||
|
list<pair<CTxDestination, int64> > listSent;
|
||||||
|
tx.GetAmounts(listReceived, listSent, nFee, strSentAccount);
|
||||||
|
printf("WalletServerSession - NotifyTransactionChanged: received: %i sent: %i", listReceived.size(), listSent.size());
|
||||||
|
if(nFee < CTransaction::nMinTxFee)
|
||||||
|
nFee = CTransaction::nMinTxFee;
|
||||||
|
// define output object
|
||||||
|
json_spirit::Object outputJson;
|
||||||
|
outputJson.push_back(json_spirit::Pair("sessionid", sessionId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("correlationid", sessionId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("command", "transaction"));
|
||||||
|
// add wallet info
|
||||||
|
json_spirit::Object result;
|
||||||
|
result.push_back(json_spirit::Pair("errorCode", 0));
|
||||||
|
result.push_back(json_spirit::Pair("errorMessage", ""));
|
||||||
|
result.push_back(json_spirit::Pair("transactionid", hash.ToString()));
|
||||||
|
result.push_back(json_spirit::Pair("transactiontime", tx.GetTxTime()));
|
||||||
|
// Send
|
||||||
|
if (!listSent.empty() || nFee != 0)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64)& s, listSent)
|
||||||
|
{
|
||||||
|
result.push_back(json_spirit::Pair("transactiontype", "SENT"));
|
||||||
|
result.push_back(json_spirit::Pair("address", CBitcoinAddress(s.first).ToString()));
|
||||||
|
result.push_back(json_spirit::Pair("amount", FormatMoney(s.second,false)));
|
||||||
|
result.push_back(json_spirit::Pair("fee", FormatMoney(nFee, false)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Received
|
||||||
|
else if (listReceived.size() > 0 && tx.GetDepthInMainChain() >= 1)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64)& r, listReceived)
|
||||||
|
{
|
||||||
|
result.push_back(json_spirit::Pair("transactiontype", "RECEIVED"));
|
||||||
|
result.push_back(json_spirit::Pair("address", CBitcoinAddress(r.first).ToString()));
|
||||||
|
result.push_back(json_spirit::Pair("amount", FormatMoney(r.second, false)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outputJson.push_back(json_spirit::Pair("result", result));
|
||||||
|
// send result to out queue
|
||||||
|
WalletServerSession::sendMessageToQueue(outputJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletServerSession::sendMessageToQueue(json_spirit::Object outputJson)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// construct a headermap
|
||||||
|
STOMP::hdrmap headers;
|
||||||
|
headers["Content-Type"] = string("application/json");
|
||||||
|
// add an outgoing message to the topic
|
||||||
|
std::string body = json_spirit::write(outputJson);
|
||||||
|
printf("WalletServerSession %s JSON: %s\n", sessionId.c_str(), body.c_str());
|
||||||
|
bool sendResult = session_stomp_client->send(WalletServer::server_out_queue, headers, body);
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
cerr << "Error in BoostStomp: " << e.what() << "\n";
|
||||||
|
}
|
||||||
|
// update last commandtime
|
||||||
|
walletServer.setLastCommandTime(sessionId, (int)time(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletServerSession::executeWalletCommand(Command data)
|
||||||
|
{
|
||||||
|
// Double check if the command is for this session before execute
|
||||||
|
if(sessionId.compare(data.sessionId) == 0)
|
||||||
|
{
|
||||||
|
if(data.command.compare("openwallet") == 0)
|
||||||
|
{
|
||||||
|
if(!walletOpen)
|
||||||
|
WalletServerSession::openWallet(data);
|
||||||
|
else
|
||||||
|
walletServer.sendErrorMessage(108, sessionId, data.correlationId, data.command);
|
||||||
|
}
|
||||||
|
else if(data.command.compare("closewallet") == 0)
|
||||||
|
{
|
||||||
|
WalletServerSession::closeWallet(data);
|
||||||
|
}
|
||||||
|
else if(data.command.compare("getinfo") == 0)
|
||||||
|
{
|
||||||
|
if(walletOpen)
|
||||||
|
WalletServerSession::getWalletInfo(data);
|
||||||
|
else
|
||||||
|
walletServer.sendErrorMessage(109, sessionId, data.correlationId, data.command);
|
||||||
|
}
|
||||||
|
else if(data.command.compare("getaddresslist") == 0)
|
||||||
|
{
|
||||||
|
if(walletOpen)
|
||||||
|
WalletServerSession::getAddressBook(data);
|
||||||
|
else
|
||||||
|
walletServer.sendErrorMessage(109, sessionId, data.correlationId, data.command);
|
||||||
|
}
|
||||||
|
else if(data.command.compare("sendtoaddress") == 0)
|
||||||
|
{
|
||||||
|
if(walletOpen)
|
||||||
|
WalletServerSession::sendCoinsToAddress(data);
|
||||||
|
else
|
||||||
|
walletServer.sendErrorMessage(109, sessionId, data.correlationId, data.command);
|
||||||
|
}
|
||||||
|
else if(data.command.compare("closesession") == 0)
|
||||||
|
{
|
||||||
|
WalletServerSession::closeSession();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("WalletServerSession command not found: %s\n", data.command.c_str());
|
||||||
|
walletServer.sendErrorMessage(110, sessionId, data.correlationId, data.command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletServerSession::closeWalletIfOpen()
|
||||||
|
{
|
||||||
|
printf("Close WalletServerSession sessionId: %s - Current WalletId: %s - Current Thread ID: %s\n",
|
||||||
|
sessionId.c_str(), walletId.c_str(), boost::lexical_cast<std::string>(boost::this_thread::get_id()).c_str());
|
||||||
|
if(walletOpen)
|
||||||
|
{
|
||||||
|
// detach and close wallet file
|
||||||
|
printf("%s detach\n", clientWallet->strWalletFile.c_str());
|
||||||
|
bitdb.dbenv.lsn_reset(clientWallet->strWalletFile.c_str(), 0);
|
||||||
|
printf("%s closed\n", clientWallet->strWalletFile.c_str());
|
||||||
|
// Create close wallet result message
|
||||||
|
json_spirit::Object outputJson;
|
||||||
|
outputJson.push_back(json_spirit::Pair("sessionid", sessionId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("command", "closewallet"));
|
||||||
|
json_spirit::Object result;
|
||||||
|
result.push_back(json_spirit::Pair("errorCode", 0));
|
||||||
|
result.push_back(json_spirit::Pair("errorMessage", ""));
|
||||||
|
outputJson.push_back(json_spirit::Pair("result", result));
|
||||||
|
// send result to out queue
|
||||||
|
WalletServerSession::sendMessageToQueue(outputJson);
|
||||||
|
// Close Queue connection
|
||||||
|
printf("WalletServerSession sessionId: %s stop stomp client.\n", this->sessionId.c_str());
|
||||||
|
this->session_stomp_client->stop();
|
||||||
|
printf("WalletServerSession sessionId: %s delete stomp client.\n", this->sessionId.c_str());
|
||||||
|
delete this->session_stomp_client;
|
||||||
|
printf("WalletServerSession sessionId: %s wallet close finished.\n", sessionId.c_str());
|
||||||
|
walletOpen = false;
|
||||||
|
walletServer.setWalletOpen(sessionId, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletServerSession::openWallet(Command data)
|
||||||
|
{
|
||||||
|
printf("WalletServerSession sessionId: %s Execute %s\n", this->sessionId.c_str(), data.command.c_str());
|
||||||
|
// define output object
|
||||||
|
json_spirit::Object outputJson;
|
||||||
|
outputJson.push_back(json_spirit::Pair("sessionid", sessionId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("correlationid", data.correlationId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("command", "openWallet"));
|
||||||
|
// get WalletId from command arguments
|
||||||
|
std::string openWalletId = "";
|
||||||
|
std::map<std::string, std::string>::iterator it;
|
||||||
|
it = data.arguments.find("walletid");
|
||||||
|
if(it != data.arguments.end())
|
||||||
|
{
|
||||||
|
openWalletId = it->second;
|
||||||
|
}
|
||||||
|
if(openWalletId.length() == 0)
|
||||||
|
{
|
||||||
|
// send error message
|
||||||
|
json_spirit::Object result;
|
||||||
|
result.push_back(json_spirit::Pair("errorCode", 101));
|
||||||
|
result.push_back(json_spirit::Pair("errorMessage", "No Wallet ID supplied in arguments array."));
|
||||||
|
outputJson.push_back(json_spirit::Pair("result", result));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// verify walletId/accountId combination is valid
|
||||||
|
bool commandValid = walletServer.isWalletAccountValid(openWalletId, data.accountId);
|
||||||
|
if(commandValid)
|
||||||
|
{
|
||||||
|
// check wallet file is available on filesystem
|
||||||
|
std::string walletFilenameString = openWalletId + ".dat";
|
||||||
|
this->walletFilename = walletServer.getWalletServerPath() / walletFilenameString;
|
||||||
|
if(boost::filesystem::exists(this->walletFilename))
|
||||||
|
{
|
||||||
|
printf("Wallet File Exists so open the wallet: %s\n", this->walletFilename.string().c_str());
|
||||||
|
// open wallet
|
||||||
|
int64 nStart = GetTimeMillis();
|
||||||
|
bool fFirstRun = true;
|
||||||
|
clientWallet = new CWallet(this->walletFilename.string());
|
||||||
|
DBErrors nLoadWalletRet = clientWallet->LoadWallet(fFirstRun);
|
||||||
|
std::ostringstream strLoadResult;
|
||||||
|
if (nLoadWalletRet != DB_LOAD_OK)
|
||||||
|
{
|
||||||
|
if (nLoadWalletRet == DB_CORRUPT)
|
||||||
|
strLoadResult << "Error loading wallet file: Wallet corrupted";
|
||||||
|
else if (nLoadWalletRet == DB_NONCRITICAL_ERROR)
|
||||||
|
{
|
||||||
|
strLoadResult << "Warning: error reading wallet file! All keys read correctly, but transaction data"
|
||||||
|
" or address book entries might be missing or incorrect.";
|
||||||
|
}
|
||||||
|
else if (nLoadWalletRet == DB_TOO_NEW)
|
||||||
|
strLoadResult << "Error loading wallet file: Wallet requires newer version of CasinoCoin";
|
||||||
|
else if (nLoadWalletRet == DB_NEED_REWRITE)
|
||||||
|
{
|
||||||
|
strLoadResult << "Wallet needed to be rewritten: restart CasinoCoin to complete";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strLoadResult << "Error loading " << walletFilenameString.c_str();
|
||||||
|
// load wallet result
|
||||||
|
printf("WalletServerSession - Load Wallet result: %s\n", strLoadResult.str().c_str());
|
||||||
|
// send error message
|
||||||
|
json_spirit::Object result;
|
||||||
|
result.push_back(json_spirit::Pair("errorCode", 103));
|
||||||
|
std::string openWalletError = std::string("Open Wallet Error: ");
|
||||||
|
openWalletError.append(strLoadResult.str());
|
||||||
|
result.push_back(json_spirit::Pair("errorMessage", openWalletError));
|
||||||
|
outputJson.push_back(json_spirit::Pair("result", result));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// connect to new Transaction Notifications
|
||||||
|
printf("WalletServerSession - Connect to new Transaction Notification\n");
|
||||||
|
clientWallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
|
||||||
|
// set wallet open in session
|
||||||
|
walletOpen = true;
|
||||||
|
walletServer.setWalletOpen(sessionId, true);
|
||||||
|
walletServer.setLastCommandTime(sessionId, (int)time(NULL));
|
||||||
|
// get blockchain best block
|
||||||
|
CBlockIndex *pindexBlockchain = pindexBest;
|
||||||
|
// get wallet genesis block
|
||||||
|
CBlockIndex *pindexWalletGenesisBlock;
|
||||||
|
CBlockLocator genesisLocator;
|
||||||
|
if(clientWallet->GetWalletGenesisBlock(genesisLocator))
|
||||||
|
pindexWalletGenesisBlock = genesisLocator.GetBlockIndex();
|
||||||
|
else
|
||||||
|
pindexWalletGenesisBlock = pindexGenesisBlock;
|
||||||
|
// get wallet best block
|
||||||
|
CBlockLocator walletLocator;
|
||||||
|
CBlockIndex *pindexWallet;
|
||||||
|
if (clientWallet->GetBestChain(walletLocator))
|
||||||
|
pindexWallet = walletLocator.GetBlockIndex();
|
||||||
|
else
|
||||||
|
pindexWallet = pindexWalletGenesisBlock;
|
||||||
|
printf("WalletServerSession - pindexBlockchain: %i pindexWallet: %i pindexWalletGenesisBlock: %i\n", pindexBlockchain->nHeight, pindexWallet->nHeight, pindexWalletGenesisBlock->nHeight);
|
||||||
|
if(pindexBlockchain->nHeight > pindexWallet->nHeight)
|
||||||
|
{
|
||||||
|
CBlockIndex *pindexRescan = pindexWallet;
|
||||||
|
if(pindexWalletGenesisBlock->nHeight > pindexRescan->nHeight)
|
||||||
|
pindexRescan = pindexWalletGenesisBlock;
|
||||||
|
printf("WalletServerSession - Rescanning last %i blocks (from block %i) for wallet %s\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight, walletFilenameString.c_str());
|
||||||
|
nStart = GetTimeMillis();
|
||||||
|
clientWallet->ScanForWalletTransactions(pindexRescan);
|
||||||
|
printf("WalletServerSession - rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
|
||||||
|
clientWallet->SetBestChain(CBlockLocator(pindexBest));
|
||||||
|
nWalletDBUpdated++;
|
||||||
|
}
|
||||||
|
// Add wallet transactions that aren't already in a block to mapTransactions
|
||||||
|
clientWallet->ReacceptWalletTransactions();
|
||||||
|
// set walletId in session
|
||||||
|
walletId = openWalletId;
|
||||||
|
// send result message to out queue
|
||||||
|
json_spirit::Object result;
|
||||||
|
result.push_back(json_spirit::Pair("errorCode", 0));
|
||||||
|
result.push_back(json_spirit::Pair("errorMessage", ""));
|
||||||
|
outputJson.push_back(json_spirit::Pair("result", result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// send error message
|
||||||
|
json_spirit::Object result;
|
||||||
|
result.push_back(json_spirit::Pair("errorCode", 103));
|
||||||
|
std::string openWalletFileError = "Wallet file " + this->walletFilename.string() + " does not exist on WalletServer.";
|
||||||
|
result.push_back(json_spirit::Pair("errorMessage", openWalletFileError));
|
||||||
|
outputJson.push_back(json_spirit::Pair("result", result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// send error message
|
||||||
|
json_spirit::Object result;
|
||||||
|
result.push_back(json_spirit::Pair("errorCode", 102));
|
||||||
|
result.push_back(json_spirit::Pair("errorMessage", "Invalid Account ID for given Wallet ID."));
|
||||||
|
outputJson.push_back(json_spirit::Pair("result", result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// send result to out queue
|
||||||
|
WalletServerSession::sendMessageToQueue(outputJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletServerSession::closeWallet(Command data)
|
||||||
|
{
|
||||||
|
printf("WalletServerSession sessionId: %s Execute closeWallet\n", sessionId.c_str(), data.command.c_str());
|
||||||
|
closeWalletIfOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
json_spirit::Value WalletServerSession::getWalletInfo(Command data)
|
||||||
|
{
|
||||||
|
printf("WalletServerSession sessionId: %s Execute getWalletInfo\n", this->sessionId.c_str(), data.command.c_str());
|
||||||
|
// define output object
|
||||||
|
json_spirit::Object outputJson;
|
||||||
|
outputJson.push_back(json_spirit::Pair("sessionid", sessionId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("correlationid", data.correlationId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("command", "getinfo"));
|
||||||
|
// add wallet info
|
||||||
|
json_spirit::Object result;
|
||||||
|
result.push_back(json_spirit::Pair("errorCode", 0));
|
||||||
|
result.push_back(json_spirit::Pair("errorMessage", ""));
|
||||||
|
result.push_back(json_spirit::Pair("version",(int)CLIENT_VERSION));
|
||||||
|
result.push_back(json_spirit::Pair("protocolversion",(int)PROTOCOL_VERSION));
|
||||||
|
result.push_back(json_spirit::Pair("blocks", (int)nBestHeight));
|
||||||
|
result.push_back(json_spirit::Pair("coinsupply", FormatMoney(GetTotalCoinSupply(nBestHeight,false),false)));
|
||||||
|
result.push_back(json_spirit::Pair("timeoffset", (boost::int64_t)GetTimeOffset()));
|
||||||
|
result.push_back(json_spirit::Pair("connections",(int)vNodes.size()));
|
||||||
|
result.push_back(json_spirit::Pair("difficulty", (double)GetDifficulty()));
|
||||||
|
if (clientWallet) {
|
||||||
|
result.push_back(json_spirit::Pair("walletversion", clientWallet->GetVersion()));
|
||||||
|
result.push_back(json_spirit::Pair("defaultaddress", CBitcoinAddress(clientWallet->vchDefaultKey.GetID()).ToString()));
|
||||||
|
result.push_back(json_spirit::Pair("balance", FormatMoney(clientWallet->GetBalance(),false)));
|
||||||
|
result.push_back(json_spirit::Pair("unconfirmedbalance", FormatMoney(clientWallet->GetUnconfirmedBalance(),false)));
|
||||||
|
balancesMapType balances = clientWallet->GetAddressBalances();
|
||||||
|
json_spirit::Array addressBalanceArray;
|
||||||
|
BOOST_FOREACH(balancesMapType::value_type balance, balances)
|
||||||
|
{
|
||||||
|
json_spirit::Object addressInfo;
|
||||||
|
addressInfo.push_back(json_spirit::Pair("address",CBitcoinAddress(balance.first).ToString()));
|
||||||
|
addressInfo.push_back(json_spirit::Pair("balance", ValueFromAmount(balance.second)));
|
||||||
|
addressBalanceArray.push_back(addressInfo);
|
||||||
|
}
|
||||||
|
result.push_back(json_spirit::Pair("addresses", addressBalanceArray));
|
||||||
|
result.push_back(json_spirit::Pair("keypoololdest",(boost::int64_t)clientWallet->GetOldestKeyPoolTime()));
|
||||||
|
result.push_back(json_spirit::Pair("keypoolsize", (int)clientWallet->GetKeyPoolSize()));
|
||||||
|
}
|
||||||
|
result.push_back(json_spirit::Pair("paytxfee", FormatMoney(CTransaction::nMinTxFee, false)));
|
||||||
|
result.push_back(json_spirit::Pair("mininput", FormatMoney(nMinimumInputValue, false)));
|
||||||
|
if (clientWallet && clientWallet->IsCrypted())
|
||||||
|
result.push_back(json_spirit::Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
|
||||||
|
outputJson.push_back(json_spirit::Pair("result", result));
|
||||||
|
// send result to out queue
|
||||||
|
WalletServerSession::sendMessageToQueue(outputJson);
|
||||||
|
return outputJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_spirit::Value WalletServerSession::getAddressBook(Command data)
|
||||||
|
{
|
||||||
|
printf("WalletServerSession sessionId: %s Execute getAddressBook\n", sessionId.c_str(), data.command.c_str());
|
||||||
|
balancesMapType balances = clientWallet->GetAddressBalances();
|
||||||
|
// define output object
|
||||||
|
json_spirit::Object outputJson;
|
||||||
|
outputJson.push_back(json_spirit::Pair("sessionid", sessionId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("correlationid", data.correlationId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("command", data.command));
|
||||||
|
// add wallet info
|
||||||
|
json_spirit::Object result;
|
||||||
|
result.push_back(json_spirit::Pair("errorCode", 0));
|
||||||
|
result.push_back(json_spirit::Pair("errorMessage", ""));
|
||||||
|
json_spirit::Array addressBalanceArray;
|
||||||
|
BOOST_FOREACH(balancesMapType::value_type balance, balances)
|
||||||
|
{
|
||||||
|
json_spirit::Object addressInfo;
|
||||||
|
addressInfo.push_back(json_spirit::Pair("address",CBitcoinAddress(balance.first).ToString()));
|
||||||
|
addressInfo.push_back(json_spirit::Pair("balance", ValueFromAmount(balance.second)));
|
||||||
|
addressBalanceArray.push_back(addressInfo);
|
||||||
|
}
|
||||||
|
result.push_back(json_spirit::Pair("addresses", addressBalanceArray));
|
||||||
|
outputJson.push_back(json_spirit::Pair("result", result));
|
||||||
|
// send result to out queue
|
||||||
|
WalletServerSession::sendMessageToQueue(outputJson);
|
||||||
|
return outputJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_spirit::Value WalletServerSession::sendCoinsToAddress(Command data)
|
||||||
|
{
|
||||||
|
std::string strAddress = "";
|
||||||
|
std::string strAmount = "";
|
||||||
|
std::string strComment = "";
|
||||||
|
// loop over arguments and get the values
|
||||||
|
std::map<std::string, std::string>::iterator argit;
|
||||||
|
for(argit = data.arguments.begin(); argit != data.arguments.end(); argit++) {
|
||||||
|
if(argit->first.compare("address")==0)
|
||||||
|
strAddress = argit->second;
|
||||||
|
else if(argit->first.compare("amount")==0)
|
||||||
|
strAmount = argit->second;
|
||||||
|
else if(argit->first.compare("comment")==0)
|
||||||
|
strComment = argit->second;
|
||||||
|
}
|
||||||
|
printf("WalletServerSession: %s sendCoinsToAddress: %s Amount: %s\n", sessionId.c_str(), strAddress.c_str(), strAmount.c_str());
|
||||||
|
// define output object
|
||||||
|
json_spirit::Object outputJson;
|
||||||
|
outputJson.push_back(json_spirit::Pair("sessionid", sessionId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("correlationid", data.correlationId));
|
||||||
|
outputJson.push_back(json_spirit::Pair("command", data.command));
|
||||||
|
// create coin address
|
||||||
|
CBitcoinAddress address(strAddress);
|
||||||
|
if (!address.IsValid())
|
||||||
|
{
|
||||||
|
// send error message
|
||||||
|
json_spirit::Object result;
|
||||||
|
result.push_back(json_spirit::Pair("errorCode", 111));
|
||||||
|
result.push_back(json_spirit::Pair("errorMessage", "Invalid CasinoCoin address."));
|
||||||
|
outputJson.push_back(json_spirit::Pair("result", result));
|
||||||
|
// send result to out queue
|
||||||
|
WalletServerSession::sendMessageToQueue(outputJson);
|
||||||
|
return outputJson;
|
||||||
|
}
|
||||||
|
// Amount
|
||||||
|
int64 nAmount;
|
||||||
|
ParseMoney(strAmount, nAmount);
|
||||||
|
if (nAmount <= 0)
|
||||||
|
{
|
||||||
|
// send error message
|
||||||
|
json_spirit::Object result;
|
||||||
|
result.push_back(json_spirit::Pair("errorCode", 112));
|
||||||
|
result.push_back(json_spirit::Pair("errorMessage", "Amount of coins to sent to address must be greater than 0."));
|
||||||
|
outputJson.push_back(json_spirit::Pair("result", result));
|
||||||
|
// send result to out queue
|
||||||
|
WalletServerSession::sendMessageToQueue(outputJson);
|
||||||
|
return outputJson;
|
||||||
|
}
|
||||||
|
// Wallet comments
|
||||||
|
CWalletTx wtx;
|
||||||
|
if(!strComment.empty())
|
||||||
|
wtx.mapValue["comment"] = strComment;
|
||||||
|
// check if wallet is locked
|
||||||
|
// if (pwalletMain->IsLocked())
|
||||||
|
// throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
|
||||||
|
// execute send
|
||||||
|
string strError = clientWallet->SendMoneyToDestination(address.Get(), nAmount, wtx);
|
||||||
|
if (strError != "")
|
||||||
|
{
|
||||||
|
// send error message
|
||||||
|
json_spirit::Object result;
|
||||||
|
result.push_back(json_spirit::Pair("errorCode", 10));
|
||||||
|
result.push_back(json_spirit::Pair("errorMessage", "Error sending coins: " + strError));
|
||||||
|
outputJson.push_back(json_spirit::Pair("result", result));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
json_spirit::Object result;
|
||||||
|
result.push_back(json_spirit::Pair("errorCode", 0));
|
||||||
|
result.push_back(json_spirit::Pair("errorMessage", ""));
|
||||||
|
result.push_back(json_spirit::Pair("txid", wtx.GetHash().GetHex()));
|
||||||
|
outputJson.push_back(json_spirit::Pair("result", result));
|
||||||
|
}
|
||||||
|
// send result to out queue
|
||||||
|
WalletServerSession::sendMessageToQueue(outputJson);
|
||||||
|
return outputJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletServerSession::closeSession()
|
||||||
|
{
|
||||||
|
printf("WalletServerSession sessionId: %s Execute closeSession\n", sessionId.c_str());
|
||||||
|
closeWalletIfOpen();
|
||||||
|
// remove wallet object
|
||||||
|
if(clientWallet != NULL)
|
||||||
|
delete clientWallet;
|
||||||
|
// set shutdownComplete
|
||||||
|
shutdownComplete = true;
|
||||||
|
printf("WalletServerSession sessionId: %s Session Close Finished!\n", sessionId.c_str());
|
||||||
|
}
|
||||||
95
src/walletserversession.h
Normal file
95
src/walletserversession.h
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#ifndef WALLETSERVERSESSION_H
|
||||||
|
#define WALLETSERVERSESSION_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "walletserver.h"
|
||||||
|
#include "wallet.h"
|
||||||
|
#include "json/json_spirit.h"
|
||||||
|
#include "stomp/booststomp.h"
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
#include <boost/thread/condition_variable.hpp>
|
||||||
|
#include <boost/thread/mutex.hpp>
|
||||||
|
|
||||||
|
typedef std::map<CTxDestination, int64> balancesMapType;
|
||||||
|
|
||||||
|
// Class that consumes objects from a queue
|
||||||
|
class WalletServerSession
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SynchronisedCommandQueue<Command>* m_queue; // The queue to use
|
||||||
|
std::string sessionId; // The id of the wallet session
|
||||||
|
std::string walletId; // The wallet id of the session
|
||||||
|
boost::filesystem::path walletFilename;
|
||||||
|
// ActiveMQ Connection
|
||||||
|
STOMP::BoostStomp* session_stomp_client;
|
||||||
|
// Wallet
|
||||||
|
CWallet* clientWallet;
|
||||||
|
bool walletOpen;
|
||||||
|
// Handle new block signal
|
||||||
|
void NotifyBlocksChanged();
|
||||||
|
// Handle new transaction signal
|
||||||
|
void NotifyTransactionChanged(CWallet *wallet, const uint256 &hash, ChangeType status);
|
||||||
|
// shutdown condition
|
||||||
|
bool shutdownComplete;
|
||||||
|
|
||||||
|
// wallet commands
|
||||||
|
void openWallet(Command data);
|
||||||
|
void closeWallet(Command data);
|
||||||
|
json_spirit::Value getWalletInfo(Command data);
|
||||||
|
json_spirit::Value getAddressBook(Command data);
|
||||||
|
json_spirit::Value sendCoinsToAddress(Command data);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructor with id and the queue to use.
|
||||||
|
WalletServerSession(std::string newSessionId, SynchronisedCommandQueue<Command>* queue);
|
||||||
|
// Destructor
|
||||||
|
~WalletServerSession();
|
||||||
|
|
||||||
|
// Default operator that starts the ActiveMQ connection and reads data from the WalletServer queue
|
||||||
|
void operator () ()
|
||||||
|
{
|
||||||
|
printf("WalletServerSession - ActiveMQ connection for session: %s\n", sessionId.c_str());
|
||||||
|
// initialize wallet pointer to NULL
|
||||||
|
clientWallet = NULL;
|
||||||
|
shutdownComplete = false;
|
||||||
|
// initiate a new BoostStomp client
|
||||||
|
session_stomp_client = new STOMP::BoostStomp(WalletServer::stomp_host, WalletServer::stomp_port);
|
||||||
|
session_stomp_client->enable_debug_msgs(false);
|
||||||
|
// start the client, (by connecting to the STOMP server)
|
||||||
|
session_stomp_client->start();
|
||||||
|
// connect to Signals
|
||||||
|
uiInterface.NotifyBlocksChanged.connect(boost::bind(&NotifyBlocksChanged, this));
|
||||||
|
printf("WalletServerSession - Start Dequeue for session: %s\n", sessionId.c_str());
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Get the data from the queue and print it
|
||||||
|
Command data = m_queue->Dequeue();
|
||||||
|
printf("Consumer Session: %s consumed: %s for session: %s ThreadID: %s\n",
|
||||||
|
sessionId.c_str(), data.command.c_str(), data.sessionId.c_str(),
|
||||||
|
boost::lexical_cast<std::string>(boost::this_thread::get_id()).c_str());
|
||||||
|
executeWalletCommand(data);
|
||||||
|
// if closesesion command then wait for shutdown complete
|
||||||
|
if(data.command.compare("closesession") == 0)
|
||||||
|
{
|
||||||
|
while(!shutdownComplete)
|
||||||
|
{
|
||||||
|
printf("Wait until closesession shutdownComplete");
|
||||||
|
MilliSleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Make sure we can be interrupted
|
||||||
|
boost::this_thread::interruption_point();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// public methods
|
||||||
|
void sendMessageToQueue(json_spirit::Object outputJson);
|
||||||
|
void executeWalletCommand(Command data);
|
||||||
|
void closeWalletIfOpen();
|
||||||
|
void setWalletOpen();
|
||||||
|
bool isWalletOpen();
|
||||||
|
void closeSession();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WALLETSERVERSESSION_H
|
||||||
Reference in New Issue
Block a user