Key origin metadata, with HD wallet support #8471

Open
wants to merge 3 commits into
from
Jump to file or symbol
Failed to load files and symbols.
+91 −3
Split
View
@@ -137,7 +137,9 @@ UniValue importprivkey(const JSONRPCRequest& request)
if (pwalletMain->HaveKey(vchAddress))
return NullUniValue;
- pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = 1;
+ CKeyMetadata& metadata = pwalletMain->mapKeyMetadata[vchAddress];
+ metadata.nCreateTime = 1;
+ metadata.SetKeyOrigin(metadata.GetKeyOrigin() | CKeyMetadata::KEY_ORIGIN_IMPORTED);
if (!pwalletMain->AddKeyPubKey(key, pubkey))
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
View
@@ -1196,6 +1196,22 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
fIsWatchonly = (*it).second.fIsWatchonly;
}
+ // convert keyflags into a string
+ CKeyID keyID;
+ uint8_t keyFlags = 0;
+ if (address.GetKeyID(keyID))
+ keyFlags = pwalletMain->mapKeyMetadata[keyID].GetKeyOrigin();
+
+ std::string keyOrigin;
+ if (keyFlags & CKeyMetadata::KEY_ORIGIN_UNKNOWN)
+ keyOrigin = "unknown";
+ if (keyFlags & CKeyMetadata::KEY_ORIGIN_ENC_WALLET)
+ keyOrigin = "encrypted";
+ else if (keyFlags & CKeyMetadata::KEY_ORIGIN_UNENC_WALLET)
+ keyOrigin = "unencrypted";
+ if (keyFlags & CKeyMetadata::KEY_ORIGIN_IMPORTED)
+ keyOrigin = "imported";
+
if (fByAccounts)
{
tallyitem& _item = mapAccountTally[strAccount];
@@ -1211,6 +1227,7 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
obj.push_back(Pair("address", address.ToString()));
obj.push_back(Pair("account", strAccount));
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
+ obj.push_back(Pair("key_origin", keyOrigin));
obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
if (!fByAccounts)
obj.push_back(Pair("label", strAccount));
View
@@ -98,6 +98,20 @@ CPubKey CWallet::GenerateNewKey()
int64_t nCreationTime = GetTime();
CKeyMetadata metadata(nCreationTime);
+ //check if the wallet supports keyflags
+ if (GetVersion() >= FEATURE_HD) {
+ if (CanSupportFeature(FEATURE_HD_KEYMETA) && SetMinVersion(FEATURE_HD_KEYMETA)) {
+ metadata.nVersion = CKeyMetadata::VERSION_WITH_META;
+ }
+ } else {
+ if (CanSupportFeature(FEATURE_KEYMETA) && SetMinVersion(FEATURE_KEYMETA)) {
+ metadata.nVersion = CKeyMetadata::VERSION_WITH_META;
+ } else if (CanSupportFeature(FEATURE_KEYFLAGS) && SetMinVersion(FEATURE_KEYFLAGS)) {
+ metadata.nVersion = CKeyMetadata::VERSION_WITH_FLAGS;
+ }
+ }
+ metadata.SetKeyOrigin(IsCrypted() ? CKeyMetadata::KEY_ORIGIN_ENC_WALLET : CKeyMetadata::KEY_ORIGIN_UNENC_WALLET);
+
// use HD key derivation if HD was enabled during wallet creation
if (IsHDEnabled()) {
DeriveNewChildKey(metadata, secret);
View
@@ -81,9 +81,12 @@ enum WalletFeature
FEATURE_WALLETCRYPT = 40000, // wallet encryption
FEATURE_COMPRPUBKEY = 60000, // compressed public keys
+ FEATURE_KEYFLAGS = 70000, // key metadata flags for storing informations like key origin
+ FEATURE_KEYMETA = 70001, // key metadata map
FEATURE_HD = 130000, // Hierarchical key derivation after BIP32 (HD Wallet)
- FEATURE_LATEST = FEATURE_COMPRPUBKEY // HD is optional, use FEATURE_COMPRPUBKEY as latest version
+ FEATURE_HD_KEYMETA = 130001, // HD + key metadata map
+ FEATURE_LATEST = FEATURE_KEYMETA // HD is optional, use FEATURE_KEYMETA as latest version
};
View
@@ -73,12 +73,22 @@ class CKeyMetadata
{
public:
static const int VERSION_BASIC=1;
+ static const int VERSION_WITH_FLAGS=2;
static const int VERSION_WITH_HDDATA=10;
- static const int CURRENT_VERSION=VERSION_WITH_HDDATA;
+ static const int VERSION_WITH_META=11;
+ static const int CURRENT_VERSION=VERSION_WITH_META;
+
+ static const uint8_t KEY_ORIGIN_UNSET = 0x0000;
+ static const uint8_t KEY_ORIGIN_UNKNOWN = 0x0001;
+ static const uint8_t KEY_ORIGIN_IMPORTED = 0x0002;
+ static const uint8_t KEY_ORIGIN_UNENC_WALLET = 0x0004;
+ static const uint8_t KEY_ORIGIN_ENC_WALLET = 0x0008;
+
int nVersion;
int64_t nCreateTime; // 0 means unknown
std::string hdKeypath; //optional HD/bip32 keypath
CKeyID hdMasterKeyID; //id of the HD masterkey used to derive this key
+ std::map<std::string, std::string> mapMeta;
CKeyMetadata()
{
@@ -94,12 +104,30 @@ class CKeyMetadata
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
+ if (ser_action.ForRead()) {
+ SetNull();
+ }
READWRITE(this->nVersion);
READWRITE(nCreateTime);
if (this->nVersion >= VERSION_WITH_HDDATA)
{
READWRITE(hdKeypath);
READWRITE(hdMasterKeyID);
+ if (nVersion >= VERSION_WITH_META) {
+ READWRITE(mapMeta);
+ }
+ }
+ else
+ if (nVersion >= VERSION_WITH_FLAGS)
+ {
+ uint8_t keyFlags;
+ if (!ser_action.ForRead()) {
+ keyFlags = GetKeyOrigin();
+ }
+ READWRITE(keyFlags);
+ if (ser_action.ForRead()) {
+ SetKeyOrigin(keyFlags);
+ }
}
}
@@ -109,6 +137,30 @@ class CKeyMetadata
nCreateTime = 0;
hdKeypath.clear();
hdMasterKeyID.SetNull();
+ mapMeta.clear();
+ }
+
+ void SetKeyOrigin(const uint8_t n) {
+ const char * const p = (const char *)&n;
+ const auto it = mapMeta.find("origin");
+ if (it == mapMeta.end()) {
+ std::string s(p, 1);
+ mapMeta["origin"] = s;
+ } else {
+ // Avoid losing additional bytes, which might be future extension
+ if (it->second.size() < 1) {
+ it->second.resize(1);
+ }
+ it->second[0] = *p;
+ }
+ }
+
+ uint8_t GetKeyOrigin() const {
+ const auto it = mapMeta.find("origin");
+ if (it == mapMeta.end() || it->second.size() < 1) {
+ return KEY_ORIGIN_UNSET;
+ }
+ return it->second[0];
}
};