Browse Source

support key replacement from json rpc. seems to work.

miguelfreitas
Miguel Freitas 11 years ago
parent
commit
0071cb31db
  1. 1
      src/bitcoinrpc.cpp
  2. 34
      src/rpcrawtransaction.cpp
  3. 18
      src/rpcwallet.cpp
  4. 27
      src/twister.cpp
  5. 2
      src/twister.h
  6. 35
      src/wallet.cpp
  7. 5
      src/wallet.h
  8. 2
      twister-test.py

1
src/bitcoinrpc.cpp

@ -1218,6 +1218,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
if (strMethod == "listunspent" && n > 1) ConvertTo<boost::int64_t>(params[1]); if (strMethod == "listunspent" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "listunspent" && n > 2) ConvertTo<Array>(params[2]); if (strMethod == "listunspent" && n > 2) ConvertTo<Array>(params[2]);
if (strMethod == "getblock" && n > 1) ConvertTo<bool>(params[1]); if (strMethod == "getblock" && n > 1) ConvertTo<bool>(params[1]);
if (strMethod == "createwalletuser" && n > 1) ConvertTo<bool>(params[1]);
if (strMethod == "getrawtransaction" && n > 1) ConvertTo<boost::int64_t>(params[1]); if (strMethod == "getrawtransaction" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "gettxout" && n > 1) ConvertTo<boost::int64_t>(params[1]); if (strMethod == "gettxout" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "gettxout" && n > 2) ConvertTo<bool>(params[2]); if (strMethod == "gettxout" && n > 2) ConvertTo<bool>(params[2]);

34
src/rpcrawtransaction.cpp

@ -11,6 +11,7 @@
#include "init.h" #include "init.h"
#include "net.h" #include "net.h"
#include "wallet.h" #include "wallet.h"
#include "twister.h"
using namespace std; using namespace std;
using namespace boost; using namespace boost;
@ -145,9 +146,9 @@ Value getrawtransaction(const Array& params, bool fHelp)
Value createrawtransaction(const Array& params, bool fHelp) Value createrawtransaction(const Array& params, bool fHelp)
{ {
if (fHelp || params.size() != 2) if (fHelp || (params.size() != 2 && params.size() != 3))
throw runtime_error( throw runtime_error(
"createrawtransaction <username> <pubKey>\n" "createrawtransaction <username> <pubKey> [signedByOldKey]\n"
"Create a transaction registering a new user\n" "Create a transaction registering a new user\n"
"Returns hex-encoded raw transaction.\n" "Returns hex-encoded raw transaction.\n"
"it is not stored in the wallet or transmitted to the network."); "it is not stored in the wallet or transmitted to the network.");
@ -165,6 +166,10 @@ Value createrawtransaction(const Array& params, bool fHelp)
throw JSONRPCError(RPC_INTERNAL_ERROR, "pubkey is not valid"); throw JSONRPCError(RPC_INTERNAL_ERROR, "pubkey is not valid");
rawTx.pubKey << vch; rawTx.pubKey << vch;
if( params.size() > 2) {
vector<unsigned char> vchSign(ParseHexV(params[2], "signedByOldKey"));
rawTx.pubKey << vchSign;
}
DoTxProofOfWork(rawTx); DoTxProofOfWork(rawTx);
@ -221,6 +226,13 @@ Value sendrawtransaction(const Array& params, bool fHelp)
uint256 hashBlock; uint256 hashBlock;
CTransaction tx2; CTransaction tx2;
fHave = GetTransaction(hashTx, tx2, hashBlock); fHave = GetTransaction(hashTx, tx2, hashBlock);
// treat replacement as !fHave
if( fHave && verifyDuplicateOrReplacementTx(tx, false, true) ) {
printf("verifyDuplicateOrReplacementTx true\n");
fHave = false;
}
if (!fHave) { if (!fHave) {
// push to local node // push to local node
CValidationState state; CValidationState state;
@ -255,6 +267,9 @@ Value sendnewusertransaction(const Array& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_PARAMETER, "username must be string"); throw JSONRPCError(RPC_INVALID_PARAMETER, "username must be string");
string strUsername = params[0].get_str(); string strUsername = params[0].get_str();
CKeyID oldKeyID;
bool replaceKey = pwalletMain->GetKeyIdBeingReplaced(strUsername, oldKeyID);
CKeyID keyID; CKeyID keyID;
if( !pwalletMain->GetKeyIdFromUsername(strUsername, keyID) ) if( !pwalletMain->GetKeyIdFromUsername(strUsername, keyID) )
throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: username must exist in wallet"); throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: username must exist in wallet");
@ -267,14 +282,27 @@ Value sendnewusertransaction(const Array& params, bool fHelp)
CTransaction txOut; CTransaction txOut;
uint256 hashBlock; uint256 hashBlock;
uint256 userhash = SerializeHash(strUsername); uint256 userhash = SerializeHash(strUsername);
if( GetTransaction(userhash, txOut, hashBlock) ) bool userInTxIndex = GetTransaction(userhash, txOut, hashBlock);
if( !replaceKey && userInTxIndex )
throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: this username exists in tx database"); throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: this username exists in tx database");
if( replaceKey && !userInTxIndex )
throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: key replacemente requires old key in tx database");
Array createTxParams; Array createTxParams;
createTxParams.push_back(strUsername); createTxParams.push_back(strUsername);
createTxParams.push_back(HexStr(pubkey)); createTxParams.push_back(HexStr(pubkey));
if( replaceKey ) {
string newPubKey((const char *)pubkey.begin(), static_cast<size_t>(pubkey.size()));
string signedByOldKey;
signedByOldKey = createSignature(newPubKey, oldKeyID);
createTxParams.push_back(HexStr(signedByOldKey));
}
Value txValue = createrawtransaction(createTxParams, false); Value txValue = createrawtransaction(createTxParams, false);
if( replaceKey ) {
pwalletMain->ForgetReplacementMap(strUsername);
}
std::string strTxHex = txValue.get_str(); std::string strTxHex = txValue.get_str();
Array sendTxParams; Array sendTxParams;
sendTxParams.push_back(strTxHex); sendTxParams.push_back(strTxHex);

18
src/rpcwallet.cpp

@ -90,9 +90,9 @@ Value getinfo(const Array& params, bool fHelp)
Value createwalletuser(const Array& params, bool fHelp) Value createwalletuser(const Array& params, bool fHelp)
{ {
if (fHelp || params.size() != 1) if (fHelp || (params.size() != 1 && params.size() != 2))
throw runtime_error( throw runtime_error(
"createwalletuser <username>\n" "createwalletuser <username> [replacekey]\n"
"Create a new key pair for user and add it to wallet\n" "Create a new key pair for user and add it to wallet\n"
"Use sendnewusertransaction to publish it to the network.\n" "Use sendnewusertransaction to publish it to the network.\n"
"Returns key secret (keep it safe)"); "Returns key secret (keep it safe)");
@ -101,18 +101,28 @@ Value createwalletuser(const Array& params, bool fHelp)
string strUsername = params[0].get_str(); string strUsername = params[0].get_str();
bool replaceKey = false;
if (params.size() > 1)
replaceKey = params[1].get_bool();
CKeyID keyID; CKeyID keyID;
if( pwalletMain->GetKeyIdFromUsername(strUsername, keyID) ) bool keyInWallet = pwalletMain->GetKeyIdFromUsername(strUsername, keyID);
if( keyInWallet && !replaceKey )
throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: this username exists in wallet"); throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: this username exists in wallet");
if( !keyInWallet && replaceKey )
throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: replacekey given but old key not in wallet");
uint256 userhash = SerializeHash(strUsername); uint256 userhash = SerializeHash(strUsername);
printf("createwalletuser: usernamehash(%s) = %s\n", strUsername.c_str(), userhash.GetHex().c_str()); printf("createwalletuser: usernamehash(%s) = %s\n", strUsername.c_str(), userhash.GetHex().c_str());
CTransaction txOut; CTransaction txOut;
uint256 hashBlock; uint256 hashBlock;
if( GetTransaction(userhash, txOut, hashBlock) ) if( GetTransaction(userhash, txOut, hashBlock) && !replaceKey )
throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: this username exists in tx database"); throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: this username exists in tx database");
if( replaceKey && !pwalletMain->MoveKeyForReplacement(strUsername) )
throw JSONRPCError(RPC_WALLET_ERROR, "Error: moving key for replacement");
// Generate a new key that is added to wallet // Generate a new key that is added to wallet
CPubKey newKey = pwalletMain->GenerateNewKey(strUsername); CPubKey newKey = pwalletMain->GenerateNewKey(strUsername);
keyID = newKey.GetID(); keyID = newKey.GetID();

27
src/twister.cpp

@ -436,22 +436,16 @@ void stopSessionTorrent()
printf("libtorrent + dht stopped\n"); printf("libtorrent + dht stopped\n");
} }
std::string createSignature(std::string const &strMessage, std::string const &strUsername) std::string createSignature(std::string const &strMessage, CKeyID &keyID)
{ {
if (pwalletMain->IsLocked()) { if (pwalletMain->IsLocked()) {
printf("createSignature: Error please enter the wallet passphrase with walletpassphrase first.\n"); printf("createSignature: Error please enter the wallet passphrase with walletpassphrase first.\n");
return std::string(); return std::string();
} }
CKeyID keyID;
if( !pwalletMain->GetKeyIdFromUsername(strUsername, keyID) ) {
printf("createSignature: user '%s' unknown.\n", strUsername.c_str());
return std::string();
}
CKey key; CKey key;
if (!pwalletMain->GetKey(keyID, key)) { if (!pwalletMain->GetKey(keyID, key)) {
printf("createSignature: private key not available for user '%s'.\n", strUsername.c_str()); printf("createSignature: private key not available for given keyid.\n");
return std::string(); return std::string();
} }
@ -468,6 +462,23 @@ std::string createSignature(std::string const &strMessage, std::string const &st
return std::string((const char *)&vchSig[0], vchSig.size()); return std::string((const char *)&vchSig[0], vchSig.size());
} }
std::string createSignature(std::string const &strMessage, std::string const &strUsername)
{
if (pwalletMain->IsLocked()) {
printf("createSignature: Error please enter the wallet passphrase with walletpassphrase first.\n");
return std::string();
}
CKeyID keyID;
if( !pwalletMain->GetKeyIdFromUsername(strUsername, keyID) ) {
printf("createSignature: user '%s' unknown.\n", strUsername.c_str());
return std::string();
}
return createSignature( strMessage, keyID );
}
bool getUserPubKey(std::string const &strUsername, CPubKey &pubkey) bool getUserPubKey(std::string const &strUsername, CPubKey &pubkey)
{ {
{ {

2
src/twister.h

@ -2,6 +2,7 @@
#define TWISTER_H #define TWISTER_H
#include "util.h" #include "util.h"
#include "key.h"
#include <boost/thread.hpp> #include <boost/thread.hpp>
#define LIBTORRENT_PORT_OFFSET 1000 #define LIBTORRENT_PORT_OFFSET 1000
@ -19,6 +20,7 @@ public:
void startSessionTorrent(boost::thread_group& threadGroup); void startSessionTorrent(boost::thread_group& threadGroup);
void stopSessionTorrent(); void stopSessionTorrent();
std::string createSignature(std::string const &strMessage, CKeyID &keyID);
std::string createSignature(std::string const &strMessage, std::string const &strUsername); std::string createSignature(std::string const &strMessage, std::string const &strUsername);
bool verifySignature(std::string const &strMessage, std::string const &strUsername, std::string const &strSign); bool verifySignature(std::string const &strMessage, std::string const &strUsername, std::string const &strSign);

35
src/wallet.cpp

@ -121,6 +121,41 @@ bool CWallet::GetUsernameFromKeyId(CKeyID keyid, std::string &username)
return false; return false;
} }
bool CWallet::MoveKeyForReplacement(std::string username)
{
for (std::map<CKeyID, CKeyMetadata>::iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++) {
if (it->second.username == username) {
mapKeyReplacement.insert(make_pair(it->first, username));
mapKeyMetadata.erase(it);
return true;
}
}
return false;
}
bool CWallet::GetKeyIdBeingReplaced(std::string username, CKeyID &keyid)
{
for (std::map<CKeyID, string>::const_iterator it = mapKeyReplacement.begin(); it != mapKeyReplacement.end(); it++) {
if (it->second == username) {
keyid = it->first;
return true;
}
}
return false;
}
bool CWallet::ForgetReplacementMap(std::string username)
{
for (std::map<CKeyID, string>::iterator it = mapKeyReplacement.begin(); it != mapKeyReplacement.end(); it++) {
if (it->second == username) {
mapKeyReplacement.erase(it);
return true;
}
}
return false;
}
bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
{ {
return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);

5
src/wallet.h

@ -84,6 +84,7 @@ public:
std::set<int64> setKeyPool; std::set<int64> setKeyPool;
std::map<CKeyID, CKeyMetadata> mapKeyMetadata; std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
std::map<CKeyID, string> mapKeyReplacement;
typedef std::map<unsigned int, CMasterKey> MasterKeyMap; typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
MasterKeyMap mapMasterKeys; MasterKeyMap mapMasterKeys;
@ -200,6 +201,10 @@ public:
// get the current wallet format (the oldest client version guaranteed to understand this wallet) // get the current wallet format (the oldest client version guaranteed to understand this wallet)
int GetVersion() { return nWalletVersion; } int GetVersion() { return nWalletVersion; }
bool MoveKeyForReplacement(std::string username);
bool GetKeyIdBeingReplaced(std::string username, CKeyID &keyid);
bool ForgetReplacementMap(std::string username);
/** Address book entry changed. /** Address book entry changed.
* @note called with lock cs_wallet held. * @note called with lock cs_wallet held.
*/ */

2
twister-test.py

@ -11,7 +11,7 @@ n = int(sys.argv[2])
datadir = "/tmp/twister%d" % n datadir = "/tmp/twister%d" % n
port = "%d" % (30000+n) port = "%d" % (30000+n)
rpcport = "%d" % (40000+n) rpcport = "%d" % (40000+n)
rpcline = " -rpcuser=user -rpcpassword=pwd -rpcport=" rpcline = " -rpcuser=user -rpcpassword=pwd -rpcallowip=127.0.0.1 -rpcport="
rpccfg = rpcline + rpcport rpccfg = rpcline + rpcport
rpccfg1 = rpcline + "40001" rpccfg1 = rpcline + "40001"

Loading…
Cancel
Save