From 8c5918b576f92cf642849ddf8dc4d0ce1f05960b Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Thu, 29 Dec 2011 02:02:30 -0800 Subject: [PATCH] More wallet work and RPC work. The first real newcoin RPC "createfamily" (to create a family of accounts) works. --- Application.cpp | 4 +-- DeterministicKeys.cpp | 1 - RPCDoor.cpp | 6 ++-- RPCDoor.h | 2 +- RPCServer.cpp | 78 +++++++++++++++++++++++++++++++++++++++---- RPCServer.h | 9 ++++- Wallet.cpp | 53 ++++++++++++++++++++++++----- Wallet.h | 7 +++- uint256.h | 8 +++-- 9 files changed, 142 insertions(+), 26 deletions(-) diff --git a/Application.cpp b/Application.cpp index 97854f8945..ad4890d42c 100644 --- a/Application.cpp +++ b/Application.cpp @@ -57,8 +57,6 @@ void Application::run() theApp->setDB(new SqliteDatabase(filename.c_str())); mDatabase->connect(); - return; // TEMPORARY - if(theConfig.PEER_PORT) { mPeerDoor=new PeerDoor(mIOService); @@ -74,6 +72,8 @@ void Application::run() std::cout << "Before Run." << std::endl; mIOService.run(); // This blocks + // temporary + return; mWallet.load(); //BOOST_LOG_TRIVIAL(info) << "Done."; diff --git a/DeterministicKeys.cpp b/DeterministicKeys.cpp index 4f6ef591ec..c969829b65 100644 --- a/DeterministicKeys.cpp +++ b/DeterministicKeys.cpp @@ -2,7 +2,6 @@ #include #include #include -#include // Functions to add CKey support for deterministic EC keys diff --git a/RPCDoor.cpp b/RPCDoor.cpp index 8e1e159348..dec0004a4b 100644 --- a/RPCDoor.cpp +++ b/RPCDoor.cpp @@ -8,7 +8,7 @@ using namespace std; using namespace boost::asio::ip; RPCDoor::RPCDoor(boost::asio::io_service& io_service) : -mAcceptor(io_service, tcp::endpoint(boost::asio::ip::address_v4::loopback(), theConfig.RPC_PORT)) + mAcceptor(io_service, tcp::endpoint(boost::asio::ip::address_v4::loopback(), theConfig.RPC_PORT)) { startListening(); @@ -24,7 +24,7 @@ void RPCDoor::startListening() boost::asio::placeholders::error)); } -bool RPCDoor::isClientAllowed(std::string ip) +bool RPCDoor::isClientAllowed(const std::string& ip) { if(ip=="127.0.0.1") return(true); return(false); @@ -45,4 +45,4 @@ void RPCDoor::handleConnect(RPCServer::pointer new_connection, }else cout << "Error: " << error;//BOOST_LOG_TRIVIAL(info) << "Error: " << error; startListening(); -} \ No newline at end of file +} diff --git a/RPCDoor.h b/RPCDoor.h index eb860dedb8..f1557dcde0 100644 --- a/RPCDoor.h +++ b/RPCDoor.h @@ -12,7 +12,7 @@ class RPCDoor void handleConnect(RPCServer::pointer new_connection, const boost::system::error_code& error); - bool isClientAllowed(std::string ip); + bool isClientAllowed(const std::string& ip); public: RPCDoor(boost::asio::io_service& io_service); }; \ No newline at end of file diff --git a/RPCServer.cpp b/RPCServer.cpp index c215e870e4..d560e57a00 100644 --- a/RPCServer.cpp +++ b/RPCServer.cpp @@ -11,6 +11,7 @@ #include "HttpReply.h" #include "Application.h" #include "RPC.h" +#include "Wallet.h" #include "Conversion.h" /* @@ -44,7 +45,7 @@ void RPCServer::handle_read(const boost::system::error_code& e, if(result) { -// mReplyStr=handleRequest(mIncomingRequest.mBody); + mReplyStr=handleRequest(mIncomingRequest.mBody); sendReply(); } else if(!result) @@ -103,17 +104,76 @@ std::string RPCServer::handleRequest(const std::string& requestStr) return( HTTPReply(200, strReply) ); } +Json::Value RPCServer::doCreateFamily(Json::Value& params) +{ +// createfamily +// createfamily +// createfamily "" +// createfamily + + std::string query; + uint160 family; + + if(params.isConvertibleTo(Json::stringValue)) query=params.asString(); + + Json::Value ret(Json::objectValue); + + if(query.empty()) + { + uint256 privKey; + family=theApp->getWallet().addFamily(privKey); + ret["PrivateGenerator"]=privKey.GetHex(); + } + else if(LocalAccountFamily::isHexPrivateKey(query)) + { + uint256 pk; + pk.SetHex(query); + family=theApp->getWallet().addFamily(pk, false); + } + else if(LocalAccountFamily::isHexPublicKey(query)) + family=theApp->getWallet().addFamily(query); + else + family=theApp->getWallet().addFamily(query, false); + if(!family) + JSONRPCError(500, "Invalid family specifier"); + + ret["FamilyIdentifier"]=family.GetHex(); + ret["ShortName"]=theApp->getWallet().getShortName(family); + ret["PublicGenerator"]=theApp->getWallet().getPubKeyHex(family); + return ret; +} + +Json::Value RPCServer::doGetAccount(Json::Value ¶ms) +{ // getaccount +} + +Json::Value RPCServer::doGetNewAccount(Json::Value ¶ms) +{ // getnewaccount +} + +Json::Value RPCServer::doLock(Json::Value ¶ms) +{ // lock + // lock +} + +Json::Value RPCServer::doUnlock(Json::Value ¶ms) +{ // unlock + // unlock "" +} + +Json::Value RPCServer::doInfo(Json::Value ¶ms) +{ // info + // info + // info +} + Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params) { + std::cerr << "RPC:" << command << std::endl; if(command== "stop") { mSocket.get_io_service().stop(); - return "newcoin server stopping"; - } - if(command=="send") - { - } if(command== "addUNL") { @@ -132,6 +192,12 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params theApp->getUNL().dumpUNL(str); return(str.c_str()); } + if(command=="createfamily") return doCreateFamily(params); + if(command=="getaccount") return doGetAccount(params); + if(command=="getnewaccount") return doGetNewAccount(params); + if(command=="lock") return doLock(params); + if(command=="unlock") return doUnlock(params); + if(command=="info") return doInfo(params); return "unknown command"; } diff --git a/RPCServer.h b/RPCServer.h index 54ab5985a7..9806a496c3 100644 --- a/RPCServer.h +++ b/RPCServer.h @@ -28,6 +28,13 @@ class RPCServer : public boost::enable_shared_from_this void sendReply(); Json::Value doCommand(const std::string& command, Json::Value& params); + + Json::Value doCreateFamily(Json::Value& params); + Json::Value doGetAccount(Json::Value& params); + Json::Value doGetNewAccount(Json::Value& params); + Json::Value doLock(Json::Value& params); + Json::Value doUnlock(Json::Value& params); + Json::Value doInfo(Json::Value& params); public: typedef boost::shared_ptr pointer; @@ -44,4 +51,4 @@ public: void connected(); -}; \ No newline at end of file +}; diff --git a/Wallet.cpp b/Wallet.cpp index abee52565a..bfab4536fc 100644 --- a/Wallet.cpp +++ b/Wallet.cpp @@ -1,6 +1,9 @@ #include +#include "openssl/rand.h" +#include "openssl/ec.h" + #include "boost/lexical_cast.hpp" #include "Wallet.h" @@ -37,14 +40,7 @@ LocalAccountFamily::LocalAccountFamily(const uint160& family, const EC_GROUP* gr mFamily(family), mLastSeq(0), mRootPrivateKey(NULL) { mRootPubKey=EC_POINT_dup(pubKey, group); -#ifdef DEBUG - std::cerr << "LocalAccountFamily::LocalAccountFamily(" << family.GetHex() << "," << std::endl; - EC_GROUP *grp=EC_GROUP_new_by_curve_name(NID_secp256k1); - char *p2h=EC_POINT_point2hex(grp, pubKey, POINT_CONVERSION_COMPRESSED, NULL); - EC_GROUP_free(grp); - std::cerr << " " << p2h << ")" << std::endl; - OPENSSL_free(p2h); -#endif + mName=family.GetHex().substr(0, 4); } LocalAccountFamily::~LocalAccountFamily() @@ -80,7 +76,6 @@ void LocalAccountFamily::lock() } } - std::string LocalAccountFamily::getPubKeyHex() const { EC_GROUP *grp=EC_GROUP_new_by_curve_name(NID_secp256k1); @@ -100,6 +95,32 @@ std::string LocalAccountFamily::getPubKeyHex() const return ret; } +static bool isHex(char j) +{ + if((j>='0') && (j<='9')) return true; + if((j>='A') && (j<='F')) return true; + if((j>='a') && (j<='f')) return true; + return false; +} + +bool LocalAccountFamily::isHexPrivateKey(const std::string& s) +{ // 64 characters, all legal hex + if(s.size()!=64) return false; + for(int i=0; i<64; i++) + if(!isHex(s[i])) return false; + return true; +} + +bool LocalAccountFamily::isHexPublicKey(const std::string& s) +{ // 66 characters, all legal hex, starts with '02' or '03' + if(s.size()!=66) return false; + if(s[0]!='0') return false; + if((s[1]!='2') && (s[2]!='3')) return false; + for(int i=3; i<66; i++) + if(!isHex(s[i])) return false; + return true; +} + std::string LocalAccountFamily::getSQLFields() { return "(FamilyName,RootPubKey,Seq,Name,Comment)"; @@ -143,6 +164,12 @@ uint160 Wallet::addFamily(const uint256& key, bool lock) return fam->getFamily(); } +uint160 Wallet::addFamily(uint256& key) +{ + RAND_bytes((unsigned char *) &key, sizeof(key)); + return addFamily(key, false); +} + uint160 Wallet::addFamily(const std::string& payPhrase, bool lock) { return addFamily(CKey::PassPhraseToKey(payPhrase), lock); @@ -230,6 +257,14 @@ std::string Wallet::getPubKeyHex(const uint160& famBase) return fit->second->getPubKeyHex(); } +std::string Wallet::getShortName(const uint160& famBase) +{ + std::map::iterator fit=families.find(famBase); + if(fit==families.end()) return ""; + assert(fit->second->getFamily()==famBase); + return fit->second->getShortName(); +} + LocalAccount::pointer Wallet::getLocalAccount(const uint160& family, int seq) { std::map::iterator fit=families.find(family); diff --git a/Wallet.h b/Wallet.h index 628215ca5e..c465c7bffd 100644 --- a/Wallet.h +++ b/Wallet.h @@ -93,10 +93,13 @@ public: uint160 getAccount(int seq); std::string getPubKeyHex() const; // The text name of the public key - std::string getShortName() const; // The text name for the family + std::string getShortName() const { return mName; } static std::string getSQLFields(); std::string getSQL() const; + + static bool isHexPrivateKey(const std::string&); + static bool isHexPublicKey(const std::string&); }; class LocalAccount @@ -145,6 +148,7 @@ public: uint160 addFamily(const std::string& passPhrase, bool lock); uint160 addFamily(const uint256& passPhrase, bool lock); uint160 addFamily(const std::string& pubKey); + uint160 addFamily(uint256& privKey); void delFamily(const uint160& familyName); @@ -156,6 +160,7 @@ public: LocalAccount::pointer getLocalAccount(const uint160& famBase, int seq); LocalAccount::pointer getLocalAccount(const uint160& acctID); std::string getPubKeyHex(const uint160& famBase); + std::string getShortName(const uint160& famBase); static bool unitTest(); }; diff --git a/uint256.h b/uint256.h index a4983c47c4..89fdfcacc3 100644 --- a/uint256.h +++ b/uint256.h @@ -296,7 +296,7 @@ public: { char psz[sizeof(pn)*2 + 1]; for (int i = 0; i < sizeof(pn); i++) - sprintf(psz + i*2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]); + sprintf(psz + i*2, "%02X", ((unsigned char*)pn)[sizeof(pn) - i - 1]); return std::string(psz, psz + sizeof(pn)*2); } @@ -314,7 +314,11 @@ public: psz += 2; // hex string to uint - static char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 }; + static char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 }; + const char* pbegin = psz; while (phexdigit[*psz] || *psz == '0') psz++;