Auto merge of #1205 - str4d:1199-key-management, r=str4d
Add support for spending keys to the basic key store Prerequisite for #1197 and #1199.
This commit is contained in:
@@ -8,6 +8,7 @@ zcash_gtest_SOURCES = \
|
|||||||
gtest/test_checktransaction.cpp \
|
gtest/test_checktransaction.cpp \
|
||||||
gtest/test_equihash.cpp \
|
gtest/test_equihash.cpp \
|
||||||
gtest/test_joinsplit.cpp \
|
gtest/test_joinsplit.cpp \
|
||||||
|
gtest/test_keystore.cpp \
|
||||||
gtest/test_noteencryption.cpp \
|
gtest/test_noteencryption.cpp \
|
||||||
gtest/test_merkletree.cpp \
|
gtest/test_merkletree.cpp \
|
||||||
gtest/test_circuit.cpp \
|
gtest/test_circuit.cpp \
|
||||||
|
|||||||
29
src/gtest/test_keystore.cpp
Normal file
29
src/gtest/test_keystore.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "keystore.h"
|
||||||
|
#include "zcash/Address.hpp"
|
||||||
|
|
||||||
|
TEST(keystore_tests, store_and_retrieve_spending_key) {
|
||||||
|
CBasicKeyStore keyStore;
|
||||||
|
libzcash::SpendingKey skOut;
|
||||||
|
|
||||||
|
std::set<libzcash::PaymentAddress> addrs;
|
||||||
|
keyStore.GetPaymentAddresses(addrs);
|
||||||
|
EXPECT_EQ(0, addrs.size());
|
||||||
|
|
||||||
|
auto sk = libzcash::SpendingKey::random();
|
||||||
|
auto addr = sk.address();
|
||||||
|
|
||||||
|
// Sanity-check: we can't get a key we haven't added
|
||||||
|
EXPECT_FALSE(keyStore.HaveSpendingKey(addr));
|
||||||
|
EXPECT_FALSE(keyStore.GetSpendingKey(addr, skOut));
|
||||||
|
|
||||||
|
keyStore.AddSpendingKey(sk);
|
||||||
|
EXPECT_TRUE(keyStore.HaveSpendingKey(addr));
|
||||||
|
EXPECT_TRUE(keyStore.GetSpendingKey(addr, skOut));
|
||||||
|
EXPECT_EQ(sk, skOut);
|
||||||
|
|
||||||
|
keyStore.GetPaymentAddresses(addrs);
|
||||||
|
EXPECT_EQ(1, addrs.size());
|
||||||
|
EXPECT_EQ(1, addrs.count(addr));
|
||||||
|
}
|
||||||
@@ -83,3 +83,10 @@ bool CBasicKeyStore::HaveWatchOnly() const
|
|||||||
LOCK(cs_KeyStore);
|
LOCK(cs_KeyStore);
|
||||||
return (!setWatchOnly.empty());
|
return (!setWatchOnly.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CBasicKeyStore::AddSpendingKey(const libzcash::SpendingKey &sk)
|
||||||
|
{
|
||||||
|
LOCK(cs_SpendingKeyStore);
|
||||||
|
mapSpendingKeys[sk.address()] = sk;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "script/script.h"
|
#include "script/script.h"
|
||||||
#include "script/standard.h"
|
#include "script/standard.h"
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
|
#include "zcash/Address.hpp"
|
||||||
|
|
||||||
#include <boost/signals2/signal.hpp>
|
#include <boost/signals2/signal.hpp>
|
||||||
#include <boost/variant.hpp>
|
#include <boost/variant.hpp>
|
||||||
@@ -20,6 +21,7 @@ class CKeyStore
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
mutable CCriticalSection cs_KeyStore;
|
mutable CCriticalSection cs_KeyStore;
|
||||||
|
mutable CCriticalSection cs_SpendingKeyStore;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~CKeyStore() {}
|
virtual ~CKeyStore() {}
|
||||||
@@ -44,11 +46,20 @@ public:
|
|||||||
virtual bool RemoveWatchOnly(const CScript &dest) =0;
|
virtual bool RemoveWatchOnly(const CScript &dest) =0;
|
||||||
virtual bool HaveWatchOnly(const CScript &dest) const =0;
|
virtual bool HaveWatchOnly(const CScript &dest) const =0;
|
||||||
virtual bool HaveWatchOnly() const =0;
|
virtual bool HaveWatchOnly() const =0;
|
||||||
|
|
||||||
|
//! Add a spending key to the store.
|
||||||
|
virtual bool AddSpendingKey(const libzcash::SpendingKey &sk) =0;
|
||||||
|
|
||||||
|
//! Check whether a spending key corresponding to a given payment address is present in the store.
|
||||||
|
virtual bool HaveSpendingKey(const libzcash::PaymentAddress &address) const =0;
|
||||||
|
virtual bool GetSpendingKey(const libzcash::PaymentAddress &address, libzcash::SpendingKey& skOut) const =0;
|
||||||
|
virtual void GetPaymentAddresses(std::set<libzcash::PaymentAddress> &setAddress) const =0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::map<CKeyID, CKey> KeyMap;
|
typedef std::map<CKeyID, CKey> KeyMap;
|
||||||
typedef std::map<CScriptID, CScript > ScriptMap;
|
typedef std::map<CScriptID, CScript > ScriptMap;
|
||||||
typedef std::set<CScript> WatchOnlySet;
|
typedef std::set<CScript> WatchOnlySet;
|
||||||
|
typedef std::map<libzcash::PaymentAddress, libzcash::SpendingKey> SpendingKeyMap;
|
||||||
|
|
||||||
/** Basic key store, that keeps keys in an address->secret map */
|
/** Basic key store, that keeps keys in an address->secret map */
|
||||||
class CBasicKeyStore : public CKeyStore
|
class CBasicKeyStore : public CKeyStore
|
||||||
@@ -57,6 +68,7 @@ protected:
|
|||||||
KeyMap mapKeys;
|
KeyMap mapKeys;
|
||||||
ScriptMap mapScripts;
|
ScriptMap mapScripts;
|
||||||
WatchOnlySet setWatchOnly;
|
WatchOnlySet setWatchOnly;
|
||||||
|
SpendingKeyMap mapSpendingKeys;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
|
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
|
||||||
@@ -103,6 +115,43 @@ public:
|
|||||||
virtual bool RemoveWatchOnly(const CScript &dest);
|
virtual bool RemoveWatchOnly(const CScript &dest);
|
||||||
virtual bool HaveWatchOnly(const CScript &dest) const;
|
virtual bool HaveWatchOnly(const CScript &dest) const;
|
||||||
virtual bool HaveWatchOnly() const;
|
virtual bool HaveWatchOnly() const;
|
||||||
|
|
||||||
|
bool AddSpendingKey(const libzcash::SpendingKey &sk);
|
||||||
|
bool HaveSpendingKey(const libzcash::PaymentAddress &address) const
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
{
|
||||||
|
LOCK(cs_SpendingKeyStore);
|
||||||
|
result = (mapSpendingKeys.count(address) > 0);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
bool GetSpendingKey(const libzcash::PaymentAddress &address, libzcash::SpendingKey &skOut) const
|
||||||
|
{
|
||||||
|
{
|
||||||
|
LOCK(cs_SpendingKeyStore);
|
||||||
|
SpendingKeyMap::const_iterator mi = mapSpendingKeys.find(address);
|
||||||
|
if (mi != mapSpendingKeys.end())
|
||||||
|
{
|
||||||
|
skOut = mi->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void GetPaymentAddresses(std::set<libzcash::PaymentAddress> &setAddress) const
|
||||||
|
{
|
||||||
|
setAddress.clear();
|
||||||
|
{
|
||||||
|
LOCK(cs_SpendingKeyStore);
|
||||||
|
SpendingKeyMap::const_iterator mi = mapSpendingKeys.begin();
|
||||||
|
while (mi != mapSpendingKeys.end())
|
||||||
|
{
|
||||||
|
setAddress.insert((*mi).first);
|
||||||
|
mi++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
|
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ public:
|
|||||||
uint256 inner() const {
|
uint256 inner() const {
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend inline bool operator==(const uint252& a, const uint252& b) { return a.contents == b.contents; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ uint256 ViewingKey::pk_enc() {
|
|||||||
return ZCNoteEncryption::generate_pubkey(*this);
|
return ZCNoteEncryption::generate_pubkey(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewingKey SpendingKey::viewing_key() {
|
ViewingKey SpendingKey::viewing_key() const {
|
||||||
return ViewingKey(ZCNoteEncryption::generate_privkey(*this));
|
return ViewingKey(ZCNoteEncryption::generate_privkey(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,8 +16,8 @@ SpendingKey SpendingKey::random() {
|
|||||||
return SpendingKey(random_uint252());
|
return SpendingKey(random_uint252());
|
||||||
}
|
}
|
||||||
|
|
||||||
PaymentAddress SpendingKey::address() {
|
PaymentAddress SpendingKey::address() const {
|
||||||
return PaymentAddress(PRF_addr_a_pk(*this), viewing_key().pk_enc());
|
return PaymentAddress(PRF_addr_a_pk(*this), viewing_key().pk_enc());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ public:
|
|||||||
READWRITE(a_pk);
|
READWRITE(a_pk);
|
||||||
READWRITE(pk_enc);
|
READWRITE(pk_enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend inline bool operator<(const PaymentAddress& a, const PaymentAddress& b) { return a.a_pk < b.a_pk; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class ViewingKey : public uint256 {
|
class ViewingKey : public uint256 {
|
||||||
@@ -38,8 +40,8 @@ public:
|
|||||||
|
|
||||||
static SpendingKey random();
|
static SpendingKey random();
|
||||||
|
|
||||||
ViewingKey viewing_key();
|
ViewingKey viewing_key() const;
|
||||||
PaymentAddress address();
|
PaymentAddress address() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user