Save generated key pairs in the wallet.dat.
Due to lack of time for a proper debugging the generation of malleable keys has been disabled on the main network. Of course it will be enabled in the near future.
{ "newmalleablekey", &newmalleablekey, false, false},
{ "adjustmalleablekey", &adjustmalleablekey, false, false},
{ "adjustmalleablepubkey", &adjustmalleablepubkey, false, false},
- { "listmalleablepubkeys", &listmalleablepubkeys, false, false},
+ { "listmalleableviews", &listmalleableviews, false, false},
+ { "dumpmalleablekey", &dumpmalleablekey, false, false},
{ "sendalert", &sendalert, false, false},
};
extern json_spirit::Value newmalleablekey(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value adjustmalleablekey(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value adjustmalleablepubkey(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value listmalleablepubkeys(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value listmalleableviews(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value dumpmalleablekey(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getrawtransaction(const json_spirit::Array& params, bool fHelp); // in rcprawtransaction.cpp
extern json_spirit::Value listunspent(const json_spirit::Array& params, bool fHelp);
return EncodeBase58Check(vch);
}
+std::vector<unsigned char> CMalleablePubKey::Raw() const
+{
+ CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
+ ssKey << *this;
+ std::vector<unsigned char> vch(ssKey.begin(), ssKey.end());
+
+ return vch;
+}
+
bool CMalleablePubKey::SetString(const std::string& strMalleablePubKey)
{
std::vector<unsigned char> vchTemp;
SetSecrets(L, H);
}
+/*
CMalleableKey& CMalleableKey::operator=(const CMalleableKey &b)
{
SetSecrets(b.vchSecretL, b.vchSecretH);
return (*this);
}
+*/
CMalleableKey::~CMalleableKey()
{
return EncodeBase58Check(vch);
}
+std::vector<unsigned char> CMalleableKey::Raw() const
+{
+ CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
+ ssKey << *this;
+ std::vector<unsigned char> vch(ssKey.begin(), ssKey.end());
+
+ return vch;
+}
+
bool CMalleableKey::SetString(const std::string& strMutableKey)
{
std::vector<unsigned char> vchTemp;
return IsNull();
}
+std::vector<unsigned char> CMalleableKeyView::Raw() const
+{
+ CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
+ ssKey << *this;
+ std::vector<unsigned char> vch(ssKey.begin(), ssKey.end());
+
+ return vch;
+}
+
+
bool CMalleableKeyView::IsNull() const
{
return nVersion != CURRENT_VERSION;
bool operator==(const CMalleablePubKey &b);
bool operator!=(const CMalleablePubKey &b) { return !(*this == b); }
+ CMalleablePubKey& operator=(const CMalleablePubKey& mpk) {
+ nVersion = mpk.nVersion;
+ pubKeyL = mpk.pubKeyL;
+ pubKeyH = mpk.pubKeyH;
+ return *this;
+ }
std::string ToString() const;
bool SetString(const std::string& strMalleablePubKey);
- uint256 GetID() const;
+
+ CKeyID GetID() const {
+ return pubKeyL.GetID();
+ }
+
+ std::vector<unsigned char> Raw() const;
CPubKey& GetL() { return pubKeyL; }
CPubKey& GetH() { return pubKeyH; }
CMalleableKey();
CMalleableKey(const CMalleableKey &b);
CMalleableKey(const CSecret &L, const CSecret &H);
- CMalleableKey& operator=(const CMalleableKey &b);
~CMalleableKey();
IMPLEMENT_SERIALIZE(
std::string ToString() const;
bool SetString(const std::string& strMalleablePubKey);
+ std::vector<unsigned char> Raw() const;
+ CMalleableKey& operator=(const CMalleableKey& mk) {
+ nVersion = mk.nVersion;
+ vchSecretL = mk.vchSecretL;
+ vchSecretH = mk.vchSecretH;
+ return *this;
+ }
void Reset();
void MakeNewKeys();
bool SetSecrets(const CSecret &pvchSecretL, const CSecret &pvchSecretH);
void GetSecrets(CSecret &pvchSecretL, CSecret &pvchSecretH) const;
+ CKeyID GetID() const {
+ return GetMalleablePubKey().GetID();
+ }
CMalleablePubKey GetMalleablePubKey() const;
bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant) const;
bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant, CKey &privKeyVariant) const;
bool IsNull() const;
std::string ToString() const;
bool SetString(const std::string& strMalleablePubKey);
+ std::vector<unsigned char> Raw() const;
+ CMalleableKeyView& operator=(const CMalleableKeyView& mkv) {
+ nVersion = mkv.nVersion;
+ vchSecretL = mkv.vchSecretL;
+ vchPubKeyH = mkv.vchPubKeyH;
+ return *this;
+ }
+ CKeyID GetID() const {
+ return GetMalleablePubKey().GetID();
+ }
CMalleablePubKey GetMalleablePubKey() const;
bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant) const;
return true;
}
+bool CBasicKeyStore::AddMalleableKey(const CMalleableKey& mKey)
+{
+ {
+ LOCK(cs_KeyStore);
+ mapMalleableKeys[CMalleableKeyView(mKey)] = mKey;
+ }
+ return true;
+}
+
bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
{
if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
return (!setWatchOnly.empty());
}
-CCryptoKeyStore::CCryptoKeyStore() : fUseCrypto(false)
-{
- std::string strMalleableKey = GetArg("-masterkey", "");
- CMalleableKey malleableKey;
- if (strMalleableKey != "")
- malleableKey.SetString(strMalleableKey);
- else
- malleableKey.MakeNewKeys();
-
- const CMalleableKeyView& keyView(malleableKey);
- mapMalleableKeys[keyView] = malleableKey;
-}
-
bool CCryptoKeyStore::SetCrypted()
{
{
// Add a key to the store.
virtual bool AddKey(const CKey& key) =0;
+ // Add a malleable key to store.
+ virtual bool AddMalleableKey(const CMalleableKey& mKey) =0;
+ virtual bool GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const =0;
+
// Check whether a key corresponding to a given address is present in the store.
virtual bool HaveKey(const CKeyID &address) const =0;
virtual bool GetKey(const CKeyID &address, CKey& keyOut) const =0;
virtual bool CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R) const =0;
virtual bool CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const =0;
- virtual void ListMalleablePubKeys(std::list<CMalleablePubKey> &malleablePubKeyList) const =0;
+ virtual void ListMalleableViews(std::list<CMalleableKeyView> &malleableViewList) const =0;
};
typedef std::map<CKeyID, std::pair<CSecret, bool> > KeyMap;
public:
bool AddKey(const CKey& key);
+ bool AddMalleableKey(const CMalleableKey& mKey);
+ bool GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const
+ {
+ {
+ LOCK(cs_KeyStore);
+ MalleableKeyMap::const_iterator mi = mapMalleableKeys.find(keyView);
+ if (mi != mapMalleableKeys.end())
+ {
+ mKey = mi->second;
+ return true;
+ }
+ }
+ return false;
+ }
+
bool HaveKey(const CKeyID &address) const
{
bool result;
return false;
}
- void ListMalleablePubKeys(std::list<CMalleablePubKey> &malleablePubKeyList) const
+ void ListMalleableViews(std::list<CMalleableKeyView> &malleableViewList) const
{
- malleablePubKeyList.clear();
+ malleableViewList.clear();
{
LOCK(cs_KeyStore);
for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
- malleablePubKeyList.push_back(mi->first.GetMalleablePubKey());
+ malleableViewList.push_back(CMalleableKeyView(mi->first));
}
}
};
bool Unlock(const CKeyingMaterial& vMasterKeyIn);
public:
- CCryptoKeyStore();
+ CCryptoKeyStore() : fUseCrypto(false) { }
bool IsCrypted() const
{
"newmalleablekey\n"
"Make a malleable public/private key pair.\n");
- CMalleableKey malleableKey;
- malleableKey.MakeNewKeys();
- CMalleablePubKey malleablePubKey = malleableKey.GetMalleablePubKey();
+ if (!fTestNet)
+ throw runtime_error("This feature has been disabled for mainNet clients");
+
+ CMalleableKeyView keyView = pwalletMain->GenerateNewMalleableKey();
+
+ CMalleableKey mKey;
+ if (!pwalletMain->GetMalleableKey(keyView, mKey))
+ throw runtime_error("Unable to generate new malleable key");
+
+ Object result;
+ result.push_back(Pair("PublicPair", mKey.GetMalleablePubKey().ToString()));
+ result.push_back(Pair("KeyView", keyView.ToString()));
+
+ return result;
+}
+
+Value dumpmalleablekey(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 1)
+ throw runtime_error (
+ "dumpmalleablekey <Key view>\n"
+ "Dump the private and public key pairs, which correspond to provided key view.\n");
- CDataStream ssPublicBytes(SER_NETWORK, PROTOCOL_VERSION);
- ssPublicBytes << malleablePubKey;
+ CMalleableKey mKey;
+ CMalleableKeyView keyView;
+ keyView.SetString(params[0].get_str());
+
+ if (!pwalletMain->GetMalleableKey(keyView, mKey))
+ throw runtime_error("There is no such item in the wallet");
Object result;
- result.push_back(Pair("PrivatePair", malleableKey.ToString()));
- result.push_back(Pair("PublicPair", malleablePubKey.ToString()));
- result.push_back(Pair("PublicBytes", HexStr(ssPublicBytes.begin(), ssPublicBytes.end())));
+ result.push_back(Pair("PrivatePair", mKey.ToString()));
+ result.push_back(Pair("PublicPair", mKey.GetMalleablePubKey().ToString()));
return result;
}
result.push_back(Pair("PubkeyVariant", HexStr(vchPubKeyVariant.Raw())));
result.push_back(Pair("KeyVariantID", CBitcoinAddress(vchPubKeyVariant.GetID()).ToString()));
-
return result;
}
-Value listmalleablepubkeys(const Array& params, bool fHelp)
+Value listmalleableviews(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
- "listmalleablepubkeys\n"
- "Get list of malleable public keys.\n");
+ "listmalleableviews\n"
+ "Get list of views for generated malleable keys.\n");
- std::list<CMalleablePubKey> keyList;
- pwalletMain->ListMalleablePubKeys(keyList);
+ std::list<CMalleableKeyView> keyViewList;
+ pwalletMain->ListMalleableViews(keyViewList);
Array result;
- BOOST_FOREACH(const CMalleablePubKey &key, keyList)
+ BOOST_FOREACH(const CMalleableKeyView &keyView, keyViewList)
{
- result.push_back(key.ToString());
+ result.push_back(keyView.ToString());
}
return result;
}
+
// network protocol versioning
//
-static const int PROTOCOL_VERSION = 60016;
+static const int PROTOCOL_VERSION = 60017;
// earlier versions not supported as of Feb 2012, and are disconnected
static const int MIN_PROTO_VERSION = 209;
return key.GetPubKey();
}
+CMalleableKeyView CWallet::GenerateNewMalleableKey()
+{
+ RandAddSeedPerfmon();
+
+ // Compressed public keys were introduced in version 0.6.0
+ SetMinVersion(FEATURE_MALLKEY);
+
+ CMalleableKey mKey;
+ mKey.MakeNewKeys();
+ const CMalleableKeyView &keyView(mKey);
+
+ // Create new metadata
+ int64_t nCreationTime = GetTime();
+ mapMalleableKeyMetadata[keyView] = CKeyMetadata(nCreationTime);
+ if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
+ nTimeFirstKey = nCreationTime;
+
+ if (!AddMalleableKey(mKey))
+ throw std::runtime_error("CWallet::GenerateNewMalleableKey() : AddMalleableKey failed");
+ return CMalleableKeyView(mKey);
+}
+
bool CWallet::AddKey(const CKey& key)
{
CPubKey pubkey = key.GetPubKey();
return true;
}
+bool CWallet::AddMalleableKey(const CMalleableKey& mKey)
+{
+ CMalleableKeyView keyView = CMalleableKeyView(mKey);
+ if (!CCryptoKeyStore::AddMalleableKey(mKey))
+ return false;
+ if (!fFileBacked)
+ return true;
+ if (!IsCrypted())
+ return CWalletDB(strWalletFile).WriteMalleableKey(keyView, mKey, mapMalleableKeyMetadata[keyView]);
+ return true;
+}
+
bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, const vector<unsigned char> &vchCryptedSecret)
{
if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
return true;
}
+bool CWallet::LoadMalleableKeyMetadata(const CMalleableKeyView &keyView, const CKeyMetadata &metadata)
+{
+ if (metadata.nCreateTime && (!nTimeFirstKey || metadata.nCreateTime < nTimeFirstKey))
+ nTimeFirstKey = metadata.nCreateTime;
+
+ mapMalleableKeyMetadata[keyView] = metadata;
+ return true;
+}
+
bool CWallet::AddCScript(const CScript& redeemScript)
{
if (!CCryptoKeyStore::AddCScript(redeemScript))
FEATURE_WALLETCRYPT = 40000, // wallet encryption
FEATURE_COMPRPUBKEY = 60000, // compressed public keys
- FEATURE_LATEST = 60000
+ FEATURE_MALLKEY = 60017,
+ FEATURE_LATEST = 60017
};
/** A key pool entry */
std::set<int64_t> setKeyPool;
std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
+ std::map<CMalleableKeyView, CKeyMetadata> mapMalleableKeyMetadata;
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
MasterKeyMap mapMasterKeys;
// keystore implementation
// Generate a new key
CPubKey GenerateNewKey();
+ CMalleableKeyView GenerateNewMalleableKey();
// Adds a key to the store, and saves it to disk.
bool AddKey(const CKey& key);
+ bool AddMalleableKey(const CMalleableKey& mKey);
// Adds a key to the store, without saving it to disk (used by LoadWallet)
bool LoadKey(const CKey& key) { return CCryptoKeyStore::AddKey(key); }
// Load metadata (used by LoadWallet)
bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata);
+ bool LoadMalleableKeyMetadata(const CMalleableKeyView &keyView, const CKeyMetadata &metadata);
+
+ // Load malleable key without saving it to disk (used by LoadWallet)
+ bool LoadMalleableKey(const CMalleableKey &mKey) { return CCryptoKeyStore::AddMalleableKey(mKey); }
bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
// Taking advantage of the fact that pair serialization
// is just the two items serialized one after the other
ssKey >> strType;
+
if (strType == "name")
{
string strAddress;
// so set the wallet birthday to the beginning of time.
pwallet->nTimeFirstKey = 1;
}
+ else if (strType == "malpair")
+ {
+ string strKey, strKeyView;
+
+ CMalleableKey mKey;
+ CMalleableKeyView keyView;
+
+ ssKey >> strKeyView;
+ ssValue >> strKey;
+
+ keyView.SetString(strKeyView);
+ mKey.SetString(strKey);
+
+ if (mKey.IsNull())
+ {
+ strErr = "Error reading wallet database: CMalleableKey is corrupt";
+ return false;
+ }
+ if (mKey.GetID() != keyView.GetID())
+ {
+ strErr = "Error reading wallet database: CMalleableKey view inconsistency";
+ return false;
+ }
+
+ if (!pwallet->LoadMalleableKey(mKey))
+ {
+ strErr = "Error reading wallet database: LoadMalleableKey failed";
+ return false;
+ }
+ }
else if (strType == "key" || strType == "wkey")
{
vector<unsigned char> vchPubKey;
}
wss.fIsEncrypted = true;
}
+ else if (strType == "malmeta")
+ {
+ string strKeyView;
+ ssKey >> strKeyView;
+
+ CMalleableKeyView keyView;
+ keyView.SetString(strKeyView);
+
+ CKeyMetadata keyMeta;
+ ssValue >> keyMeta;
+ wss.nKeyMeta++;
+
+ pwallet->LoadMalleableKeyMetadata(keyView, keyMeta);
+ }
else if (strType == "keymeta")
{
CPubKey vchPubKey;
static bool IsKeyType(string strType)
{
return (strType== "key" || strType == "wkey" ||
- strType == "mkey" || strType == "ckey");
+ strType == "mkey" || strType == "ckey" || strType == "malpair");
}
DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
return true;
}
+ bool WriteMalleableKey(const CMalleableKeyView& keyView, const CMalleableKey& malleableKey, const CKeyMetadata &keyMeta)
+ {
+ nWalletDBUpdated++;
+ if(!Write(std::make_pair(std::string("malmeta"), keyView.ToString()), keyMeta))
+ return false;
+
+ if(!Write(std::make_pair(std::string("malpair"), keyView.ToString()), malleableKey.ToString(), false))
+ return false;
+
+ return true;
+ }
+
+
bool WriteCryptedKey(const CPubKey& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, const CKeyMetadata &keyMeta)
{
nWalletDBUpdated++;