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 @@ -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 > 2) ConvertTo<Array>(params[2]);
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 == "gettxout" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "gettxout" && n > 2) ConvertTo<bool>(params[2]);

34
src/rpcrawtransaction.cpp

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

18
src/rpcwallet.cpp

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

27
src/twister.cpp

@ -436,22 +436,16 @@ void stopSessionTorrent() @@ -436,22 +436,16 @@ void stopSessionTorrent()
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()) {
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();
}
CKey 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();
}
@ -468,6 +462,23 @@ std::string createSignature(std::string const &strMessage, std::string const &st @@ -468,6 +462,23 @@ std::string createSignature(std::string const &strMessage, std::string const &st
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)
{
{

2
src/twister.h

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

35
src/wallet.cpp

@ -121,6 +121,41 @@ bool CWallet::GetUsernameFromKeyId(CKeyID keyid, std::string &username) @@ -121,6 +121,41 @@ bool CWallet::GetUsernameFromKeyId(CKeyID keyid, std::string &username)
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)
{
return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);

5
src/wallet.h

@ -84,6 +84,7 @@ public: @@ -84,6 +84,7 @@ public:
std::set<int64> setKeyPool;
std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
std::map<CKeyID, string> mapKeyReplacement;
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
MasterKeyMap mapMasterKeys;
@ -200,6 +201,10 @@ public: @@ -200,6 +201,10 @@ public:
// get the current wallet format (the oldest client version guaranteed to understand this wallet)
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.
* @note called with lock cs_wallet held.
*/

2
twister-test.py

@ -11,7 +11,7 @@ n = int(sys.argv[2]) @@ -11,7 +11,7 @@ n = int(sys.argv[2])
datadir = "/tmp/twister%d" % n
port = "%d" % (30000+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
rpccfg1 = rpcline + "40001"

Loading…
Cancel
Save